1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _LINUX_TIMENS_H 3#define _LINUX_TIMENS_H 4 5 6#include <linux/sched.h> 7#include <linux/nsproxy.h> 8#include <linux/ns_common.h> 9#include <linux/err.h> 10#include <linux/time64.h> 11 12struct user_namespace; 13extern struct user_namespace init_user_ns; 14 15struct vm_area_struct; 16 17struct timens_offsets { 18 struct timespec64 monotonic; 19 struct timespec64 boottime; 20}; 21 22struct time_namespace { 23 struct user_namespace *user_ns; 24 struct ucounts *ucounts; 25 struct ns_common ns; 26 struct timens_offsets offsets; 27 struct page *vvar_page; 28 /* If set prevents changing offsets after any task joined namespace. */ 29 bool frozen_offsets; 30} __randomize_layout; 31 32extern struct time_namespace init_time_ns; 33 34#ifdef CONFIG_TIME_NS 35extern int vdso_join_timens(struct task_struct *task, 36 struct time_namespace *ns); 37extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns); 38 39static inline struct time_namespace *get_time_ns(struct time_namespace *ns) 40{ 41 refcount_inc(&ns->ns.count); 42 return ns; 43} 44 45struct time_namespace *copy_time_ns(unsigned long flags, 46 struct user_namespace *user_ns, 47 struct time_namespace *old_ns); 48void free_time_ns(struct time_namespace *ns); 49void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk); 50struct page *find_timens_vvar_page(struct vm_area_struct *vma); 51 52static inline void put_time_ns(struct time_namespace *ns) 53{ 54 if (refcount_dec_and_test(&ns->ns.count)) 55 free_time_ns(ns); 56} 57 58void proc_timens_show_offsets(struct task_struct *p, struct seq_file *m); 59 60struct proc_timens_offset { 61 int clockid; 62 struct timespec64 val; 63}; 64 65int proc_timens_set_offset(struct file *file, struct task_struct *p, 66 struct proc_timens_offset *offsets, int n); 67 68static inline void timens_add_monotonic(struct timespec64 *ts) 69{ 70 struct timens_offsets *ns_offsets = ¤t->nsproxy->time_ns->offsets; 71 72 *ts = timespec64_add(*ts, ns_offsets->monotonic); 73} 74 75static inline void timens_add_boottime(struct timespec64 *ts) 76{ 77 struct timens_offsets *ns_offsets = ¤t->nsproxy->time_ns->offsets; 78 79 *ts = timespec64_add(*ts, ns_offsets->boottime); 80} 81 82static inline u64 timens_add_boottime_ns(u64 nsec) 83{ 84 struct timens_offsets *ns_offsets = ¤t->nsproxy->time_ns->offsets; 85 86 return nsec + timespec64_to_ns(&ns_offsets->boottime); 87} 88 89static inline void timens_sub_boottime(struct timespec64 *ts) 90{ 91 struct timens_offsets *ns_offsets = ¤t->nsproxy->time_ns->offsets; 92 93 *ts = timespec64_sub(*ts, ns_offsets->boottime); 94} 95 96ktime_t do_timens_ktime_to_host(clockid_t clockid, ktime_t tim, 97 struct timens_offsets *offsets); 98 99static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim) 100{ 101 struct time_namespace *ns = current->nsproxy->time_ns; 102 103 if (likely(ns == &init_time_ns)) 104 return tim; 105 106 return do_timens_ktime_to_host(clockid, tim, &ns->offsets); 107} 108 109#else 110static inline int vdso_join_timens(struct task_struct *task, 111 struct time_namespace *ns) 112{ 113 return 0; 114} 115 116static inline void timens_commit(struct task_struct *tsk, 117 struct time_namespace *ns) 118{ 119} 120 121static inline struct time_namespace *get_time_ns(struct time_namespace *ns) 122{ 123 return NULL; 124} 125 126static inline void put_time_ns(struct time_namespace *ns) 127{ 128} 129 130static inline 131struct time_namespace *copy_time_ns(unsigned long flags, 132 struct user_namespace *user_ns, 133 struct time_namespace *old_ns) 134{ 135 if (flags & CLONE_NEWTIME) 136 return ERR_PTR(-EINVAL); 137 138 return old_ns; 139} 140 141static inline void timens_on_fork(struct nsproxy *nsproxy, 142 struct task_struct *tsk) 143{ 144 return; 145} 146 147static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma) 148{ 149 return NULL; 150} 151 152static inline void timens_add_monotonic(struct timespec64 *ts) { } 153static inline void timens_add_boottime(struct timespec64 *ts) { } 154 155static inline u64 timens_add_boottime_ns(u64 nsec) 156{ 157 return nsec; 158} 159 160static inline void timens_sub_boottime(struct timespec64 *ts) { } 161 162static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim) 163{ 164 return tim; 165} 166#endif 167 168struct vdso_data *arch_get_vdso_data(void *vvar_page); 169 170#endif /* _LINUX_TIMENS_H */ 171