diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-18 16:56:25 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-18 16:56:25 -0700 |
| commit | 104a813376837da3b9651457d6fdc99596257fba (patch) | |
| tree | 282c3904ed84cd479c3d7d472c77979938bb0967 /lib | |
| parent | 3b4128b9f374b4219eb716f4ad8a307bc7eb3d84 (diff) | |
| parent | 92e785d887a8a61a897289f2b342f754cf02551b (diff) | |
Merge tag 'timers-vdso-2026-08-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull VDSO updates from Thomas Gleixner:
- Consolidate the VDSO datastore further and provide support for
mlock_all() and prefaulting.
- Provide 32-bit legacy time related functionality only if
CONFIG_COMPAT_32BIT_TIME is enabled. The config switch exists,
but architecture code still exposes the legacy functionality even
disabled.
Clean this up by adding the missing guards and validating at build
time that the VDSO is legacy free if disabled.
- Consolidate the VDSO related config options in core and drivers,
which removes some non-sensical dependencies and quite an amount of
#ifdeffery.
- Clean up the PAGE_SIZE definition maze
* tag 'timers-vdso-2026-08-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (30 commits)
random: vDSO: Drop custom PAGE_SIZE definitions
LoongArch: Remove CONFIG_GENERIC_GETTIMEOFDAY ifdeffery
clocksource/drivers/timer-riscv: Remove CONFIG_GENERIC_GETTIMEOFDAY ifdeffery
clocksource/drivers/arm_arch_timer: Remove CONFIG_GENERIC_GETTIMEOFDAY ifdeffery
clocksource/drivers/mips-gic-timer: Remove CONFIG_GENERIC_GETTIMEOFDAY ifdeffery
MIPS: csrc-r4k: Remove CONFIG_GENERIC_GETTIMEOFDAY ifdeffery
vDSO: Make clockmode constants available without CONFIG_GENERIC_GETTIMEOFDAY
kbuild: Support generated asm-headers in subdirectories
vdso: Rename HAVE_GENERIC_VDSO to VDSO_DATASTORE
vdso: Drop HAVE_GENERIC_VDSO from architecture kconfig files
vdso: Automatically select HAVE_GENERIC_VDSO if necessary
MIPS: vdso: Stop using CONFIG_HAVE_GENERIC_VDSO
vdso: Remove the dependency on HAVE_GENERIC_VDSO from ARCH_HAS_VDSO_ARCH_DATA
futex: Remove dependency on HAVE_GENERIC_VDSO from FUTEX_ROBUST_UNLOCK
vdso/gettimeofday: Verify COMPAT_32BIT_TIME interactions
sparc: vdso: Respect COMPAT_32BIT_TIME
MIPS: VDSO: Respect COMPAT_32BIT_TIME
powerpc/vdso: Respect COMPAT_32BIT_TIME
ARM: VDSO: Respect COMPAT_32BIT_TIME
arm64: vdso32: Respect COMPAT_32BIT_TIME
...
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/vdso/Kconfig | 8 | ||||
| -rw-r--r-- | lib/vdso/Makefile | 2 | ||||
| -rw-r--r-- | lib/vdso/datastore.c | 65 | ||||
| -rw-r--r-- | lib/vdso/getrandom.c | 6 | ||||
| -rw-r--r-- | lib/vdso/gettimeofday.c | 20 |
5 files changed, 55 insertions, 46 deletions
diff --git a/lib/vdso/Kconfig b/lib/vdso/Kconfig index db87ba34ef19..597f5f0f9681 100644 --- a/lib/vdso/Kconfig +++ b/lib/vdso/Kconfig @@ -1,12 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 -config HAVE_GENERIC_VDSO +config VDSO_DATASTORE bool -if HAVE_GENERIC_VDSO - config GENERIC_GETTIMEOFDAY bool + select VDSO_DATASTORE help This is a generic implementation of gettimeofday vdso. Each architecture that enables this feature has to @@ -21,7 +20,6 @@ config GENERIC_VDSO_OVERFLOW_PROTECT config VDSO_GETRANDOM bool + select VDSO_DATASTORE help Selected by architectures that support vDSO getrandom(). - -endif diff --git a/lib/vdso/Makefile b/lib/vdso/Makefile index 405f743253d7..ac304def42d6 100644 --- a/lib/vdso/Makefile +++ b/lib/vdso/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_HAVE_GENERIC_VDSO) += datastore.o +obj-$(CONFIG_VDSO_DATASTORE) += datastore.o diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c index 17d37b82ebc6..1426bf4e0c12 100644 --- a/lib/vdso/datastore.c +++ b/lib/vdso/datastore.c @@ -29,10 +29,11 @@ struct vdso_arch_data *vdso_k_arch_data __ro_after_init = (void *)&vdso_initdata[VDSO_ARCH_PAGES_START * PAGE_SIZE]; #endif /* CONFIG_ARCH_HAS_VDSO_ARCH_DATA */ +static struct page *vdso_data_pages __ro_after_init; + void __init vdso_setup_data_pages(void) { unsigned int order = get_order(VDSO_NR_PAGES * PAGE_SIZE); - struct page *pages; /* * Allocate the data pages dynamically. SPARC does not support mapping @@ -42,24 +43,24 @@ void __init vdso_setup_data_pages(void) * Do not use folios. In time namespaces the pages are mapped in a different order * to userspace, which is not handled by the folio optimizations in finish_fault(). */ - pages = alloc_pages(GFP_KERNEL, order); - if (!pages) + vdso_data_pages = alloc_pages(GFP_KERNEL, order); + if (!vdso_data_pages) panic("Unable to allocate VDSO storage pages"); /* The pages are mapped one-by-one into userspace and each one needs to be refcounted. */ - split_page(pages, order); + split_page(vdso_data_pages, order); /* Move the data already written by other subsystems to the new pages */ - memcpy(page_address(pages), vdso_initdata, VDSO_NR_PAGES * PAGE_SIZE); + memcpy(page_address(vdso_data_pages), vdso_initdata, VDSO_NR_PAGES * PAGE_SIZE); if (IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY)) - vdso_k_time_data = page_address(pages + VDSO_TIME_PAGE_OFFSET); + vdso_k_time_data = page_address(vdso_data_pages + VDSO_TIME_PAGE_OFFSET); if (IS_ENABLED(CONFIG_VDSO_GETRANDOM)) - vdso_k_rng_data = page_address(pages + VDSO_RNG_PAGE_OFFSET); + vdso_k_rng_data = page_address(vdso_data_pages + VDSO_RNG_PAGE_OFFSET); if (IS_ENABLED(CONFIG_ARCH_HAS_VDSO_ARCH_DATA)) - vdso_k_arch_data = page_address(pages + VDSO_ARCH_PAGES_START); + vdso_k_arch_data = page_address(vdso_data_pages + VDSO_ARCH_PAGES_START); } static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, @@ -67,27 +68,28 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, { struct page *page, *timens_page; + if (unlikely(vmf->flags & FAULT_FLAG_REMOTE)) + return VM_FAULT_SIGBUS; + + page = vdso_data_pages + vmf->pgoff; timens_page = find_timens_vvar_page(vma); switch (vmf->pgoff) { case VDSO_TIME_PAGE_OFFSET: - if (!IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY)) - return VM_FAULT_SIGBUS; - page = virt_to_page(vdso_k_time_data); - if (timens_page) { - /* - * Fault in VVAR page too, since it will be accessed - * to get clock data anyway. - */ - unsigned long addr; - vm_fault_t err; - - addr = vmf->address + VDSO_TIMENS_PAGE_OFFSET * PAGE_SIZE; - err = vmf_insert_page(vma, addr, page); - if (unlikely(err & VM_FAULT_ERROR)) - return err; - page = timens_page; - } + if (!IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY) || !timens_page) + break; + /* + * Fault in VVAR page too, since it will be accessed + * to get clock data anyway. + */ + unsigned long addr; + vm_fault_t err; + + addr = vmf->address + VDSO_TIMENS_PAGE_OFFSET * PAGE_SIZE; + err = vmf_insert_page(vma, addr, page); + if (unlikely(err & VM_FAULT_ERROR)) + return err; + page = timens_page; break; case VDSO_TIMENS_PAGE_OFFSET: /* @@ -98,18 +100,11 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, * See also the comment near timens_setup_vdso_data(). */ if (!IS_ENABLED(CONFIG_TIME_NS) || !timens_page) - return VM_FAULT_SIGBUS; - page = virt_to_page(vdso_k_time_data); + break; + page = vdso_data_pages + VDSO_TIME_PAGE_OFFSET; break; case VDSO_RNG_PAGE_OFFSET: - if (!IS_ENABLED(CONFIG_VDSO_GETRANDOM)) - return VM_FAULT_SIGBUS; - page = virt_to_page(vdso_k_rng_data); - break; case VDSO_ARCH_PAGES_START ... VDSO_ARCH_PAGES_END: - if (!IS_ENABLED(CONFIG_ARCH_HAS_VDSO_ARCH_DATA)) - return VM_FAULT_SIGBUS; - page = virt_to_page(vdso_k_arch_data) + vmf->pgoff - VDSO_ARCH_PAGES_START; break; default: return VM_FAULT_SIGBUS; @@ -128,7 +123,7 @@ const struct vm_special_mapping vdso_vvar_mapping = { struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned long addr) { return _install_special_mapping(mm, addr, VDSO_NR_PAGES * PAGE_SIZE, - VM_READ | VM_MAYREAD | VM_IO | VM_DONTDUMP | + VM_READ | VM_MAYREAD | VM_DONTDUMP | VM_MIXEDMAP | VM_SEALED_SYSMAP, &vdso_vvar_mapping); } diff --git a/lib/vdso/getrandom.c b/lib/vdso/getrandom.c index 7e29005aa208..2851afa9154f 100644 --- a/lib/vdso/getrandom.c +++ b/lib/vdso/getrandom.c @@ -8,6 +8,7 @@ #include <vdso/datapage.h> #include <vdso/getrandom.h> #include <vdso/limits.h> +#include <vdso/page.h> #include <vdso/unaligned.h> #include <asm/barrier.h> #include <asm/vdso/getrandom.h> @@ -18,11 +19,6 @@ /* Bring in default accessors */ #include <vdso/vsyscall.h> -#undef PAGE_SIZE -#undef PAGE_MASK -#define PAGE_SIZE (1UL << CONFIG_PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE - 1)) - #define MEMCPY_AND_ZERO_SRC(type, dst, src, len) do { \ while (len >= sizeof(type)) { \ __put_unaligned_t(type, __get_unaligned_t(type, src), dst); \ diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c index e0f289d3d110..f7a591aba59f 100644 --- a/lib/vdso/gettimeofday.c +++ b/lib/vdso/gettimeofday.c @@ -12,6 +12,8 @@ #include <vdso/time32.h> #include <vdso/time64.h> +#include <uapi/linux/unistd.h> + /* * The generic vDSO implementation requires that gettimeofday.h * provides: @@ -23,6 +25,8 @@ */ #include <asm/vdso/gettimeofday.h> +#include <linux/build_bug.h> + /* Bring in default accessors */ #include <vdso/vsyscall.h> @@ -323,6 +327,8 @@ __cvdso_clock_gettime32_data(const struct vdso_time_data *vd, clockid_t clock, struct __kernel_timespec ts; bool ok; + BUILD_BUG_ON(!IS_ENABLED(CONFIG_COMPAT_32BIT_TIME)); + ok = __cvdso_clock_gettime_common(vd, clock, &ts); if (unlikely(!ok)) @@ -348,6 +354,12 @@ __cvdso_gettimeofday_data(const struct vdso_time_data *vd, { const struct vdso_clock *vc = vd->clock_data; +#ifndef __NR_gettimeofday + BUILD_BUG(); +#endif + + BUILD_BUG_ON(sizeof(tv->tv_sec) != 8 && !IS_ENABLED(CONFIG_COMPAT_32BIT_TIME)); + if (likely(tv != NULL)) { struct __kernel_timespec ts; @@ -382,6 +394,12 @@ __cvdso_time_data(const struct vdso_time_data *vd, __kernel_old_time_t *time) const struct vdso_clock *vc = vd->clock_data; __kernel_old_time_t t; +#ifndef __NR_time + BUILD_BUG(); +#endif + + BUILD_BUG_ON(sizeof(*time) != 8 && !IS_ENABLED(CONFIG_COMPAT_32BIT_TIME)); + if (vdso_is_timens_clock(vc)) { vd = vdso_timens_data(vd); vc = vd->clock_data; @@ -471,6 +489,8 @@ __cvdso_clock_getres_time32_data(const struct vdso_time_data *vd, clockid_t cloc struct __kernel_timespec ts; bool ok; + BUILD_BUG_ON(!IS_ENABLED(CONFIG_COMPAT_32BIT_TIME)); + ok = __cvdso_clock_getres_common(vd, clock, &ts); if (unlikely(!ok)) |
