]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
timens: Remove dependency on the vDSO
authorThomas Weißschuh <thomas.weissschuh@linutronix.de>
Thu, 26 Mar 2026 11:42:31 +0000 (12:42 +0100)
committerThomas Gleixner <tglx@kernel.org>
Thu, 26 Mar 2026 14:44:23 +0000 (15:44 +0100)
Previously, missing time namespace support in the vDSO meant that time
namespaces needed to be disabled globally. This was expressed in a hard
dependency on the generic vDSO library. This also meant that architectures
without any vDSO or only a stub vDSO could not enable time namespaces.
Now that all architectures using a real vDSO are using the generic library,
that dependency is not necessary anymore.

Remove the dependency and let all architectures enable time namespaces.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260326-vdso-timens-decoupling-v2-2-c82693a7775f@linutronix.de
include/linux/time_namespace.h
init/Kconfig
kernel/time/Makefile
kernel/time/namespace.c
kernel/time/namespace_internal.h
kernel/time/namespace_vdso.c

index 0421bf1b13d7a9116de46c7d1aaed16eecd687b4..c1de21a27c340c91cbc09af001052960c5064ec4 100644 (file)
@@ -25,7 +25,9 @@ struct time_namespace {
        struct ucounts          *ucounts;
        struct ns_common        ns;
        struct timens_offsets   offsets;
+#ifdef CONFIG_TIME_NS_VDSO
        struct page             *vvar_page;
+#endif
        /* If set prevents changing offsets after any task joined namespace. */
        bool                    frozen_offsets;
 } __randomize_layout;
@@ -38,7 +40,6 @@ static inline struct time_namespace *to_time_ns(struct ns_common *ns)
        return container_of(ns, struct time_namespace, ns);
 }
 void __init time_ns_init(void);
-extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
 
 static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
 {
@@ -51,7 +52,6 @@ struct time_namespace *copy_time_ns(u64 flags,
                                    struct time_namespace *old_ns);
 void free_time_ns(struct time_namespace *ns);
 void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);
-struct page *find_timens_vvar_page(struct vm_area_struct *vma);
 
 static inline void put_time_ns(struct time_namespace *ns)
 {
@@ -115,11 +115,6 @@ static inline void __init time_ns_init(void)
 {
 }
 
-static inline void timens_commit(struct task_struct *tsk,
-                                struct time_namespace *ns)
-{
-}
-
 static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
 {
        return NULL;
@@ -146,11 +141,6 @@ static inline void timens_on_fork(struct nsproxy *nsproxy,
        return;
 }
 
-static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
-       return NULL;
-}
-
 static inline void timens_add_monotonic(struct timespec64 *ts) { }
 static inline void timens_add_boottime(struct timespec64 *ts) { }
 
@@ -167,4 +157,18 @@ static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
 }
 #endif
 
+#ifdef CONFIG_TIME_NS_VDSO
+extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
+struct page *find_timens_vvar_page(struct vm_area_struct *vma);
+#else /* !CONFIG_TIME_NS_VDSO */
+static inline void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
+{
+}
+
+static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
+{
+       return NULL;
+}
+#endif /* CONFIG_TIME_NS_VDSO */
+
 #endif /* _LINUX_TIMENS_H */
index 444ce811ea674a402db3056bcf3784db78fe13e0..5e710b03a27ad1c03282ef1614e59f0818c40735 100644 (file)
@@ -1386,12 +1386,14 @@ config UTS_NS
 
 config TIME_NS
        bool "TIME namespace"
-       depends on GENERIC_GETTIMEOFDAY
        default y
        help
          In this namespace boottime and monotonic clocks can be set.
          The time will keep going with the same pace.
 
+config TIME_NS_VDSO
+       def_bool TIME_NS && GENERIC_GETTIMEOFDAY
+
 config IPC_NS
        bool "IPC namespace"
        depends on (SYSVIPC || POSIX_MQUEUE)
index 662bccb3b7f9a0e08c3ad5639211c772a980e654..eaf290c972f9552b9b2a87be282f867188060d2f 100644 (file)
@@ -29,6 +29,7 @@ endif
 obj-$(CONFIG_GENERIC_GETTIMEOFDAY)             += vsyscall.o
 obj-$(CONFIG_DEBUG_FS)                         += timekeeping_debug.o
 obj-$(CONFIG_TEST_UDELAY)                      += test_udelay.o
-obj-$(CONFIG_TIME_NS)                          += namespace.o namespace_vdso.o
+obj-$(CONFIG_TIME_NS)                          += namespace.o
+obj-$(CONFIG_TIME_NS_VDSO)                     += namespace_vdso.o
 obj-$(CONFIG_TEST_CLOCKSOURCE_WATCHDOG)                += clocksource-wdtest.o
 obj-$(CONFIG_TIME_KUNIT_TEST)                  += time_test.o
index 903f55a2dfb2a787caf527ac53f86a55a17308d8..42302cc3f3fb8daa3569e6da9d5f1d2be2982a69 100644 (file)
@@ -93,8 +93,8 @@ static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
        if (!ns)
                goto fail_dec;
 
-       ns->vvar_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
-       if (!ns->vvar_page)
+       err = timens_vdso_alloc_vvar_page(ns);
+       if (err)
                goto fail_free;
 
        err = ns_common_init(ns);
@@ -109,7 +109,7 @@ static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
        return ns;
 
 fail_free_page:
-       __free_page(ns->vvar_page);
+       timens_vdso_free_vvar_page(ns);
 fail_free:
        kfree(ns);
 fail_dec:
@@ -146,7 +146,7 @@ void free_time_ns(struct time_namespace *ns)
        dec_time_namespaces(ns->ucounts);
        put_user_ns(ns->user_ns);
        ns_common_free(ns);
-       __free_page(ns->vvar_page);
+       timens_vdso_free_vvar_page(ns);
        /* Concurrent nstree traversal depends on a grace period. */
        kfree_rcu(ns, ns.ns_rcu);
 }
index e85da11abb4d9b730e473af581c46f543bb79876..b37ba179f43b27a1f2cb2c78d649ac9aece83ed9 100644 (file)
@@ -4,10 +4,25 @@
 
 #include <linux/mutex.h>
 
+struct time_namespace;
+
 /*
  * Protects possibly multiple offsets writers racing each other
  * and tasks entering the namespace.
  */
 extern struct mutex timens_offset_lock;
 
+#ifdef CONFIG_TIME_NS_VDSO
+int timens_vdso_alloc_vvar_page(struct time_namespace *ns);
+void timens_vdso_free_vvar_page(struct time_namespace *ns);
+#else /* !CONFIG_TIME_NS_VDSO */
+static inline int timens_vdso_alloc_vvar_page(struct time_namespace *ns)
+{
+       return 0;
+}
+static inline void timens_vdso_free_vvar_page(struct time_namespace *ns)
+{
+}
+#endif /* CONFIG_TIME_NS_VDSO */
+
 #endif /* _TIME_NAMESPACE_INTERNAL_H */
index 0e154f9015012cd4e832b7e45968a1eec0f3ce32..88c075cd16a36170d175df8f1eedc755900af364 100644 (file)
@@ -144,3 +144,17 @@ void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
        timens_set_vvar_page(tsk, ns);
        vdso_join_timens(tsk, ns);
 }
+
+int timens_vdso_alloc_vvar_page(struct time_namespace *ns)
+{
+       ns->vvar_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
+       if (!ns->vvar_page)
+               return -ENOMEM;
+
+       return 0;
+}
+
+void timens_vdso_free_vvar_page(struct time_namespace *ns)
+{
+       __free_page(ns->vvar_page);
+}