xref: /linux-6.15/include/linux/time_namespace.h (revision ac1a42f4)
1769071acSAndrei Vagin /* SPDX-License-Identifier: GPL-2.0 */
2769071acSAndrei Vagin #ifndef _LINUX_TIMENS_H
3769071acSAndrei Vagin #define _LINUX_TIMENS_H
4769071acSAndrei Vagin 
5769071acSAndrei Vagin 
6769071acSAndrei Vagin #include <linux/sched.h>
7769071acSAndrei Vagin #include <linux/nsproxy.h>
8769071acSAndrei Vagin #include <linux/ns_common.h>
9769071acSAndrei Vagin #include <linux/err.h>
10058e0529SKent Overstreet #include <linux/time64.h>
11769071acSAndrei Vagin 
12769071acSAndrei Vagin struct user_namespace;
13769071acSAndrei Vagin extern struct user_namespace init_user_ns;
14769071acSAndrei Vagin 
15*6060ef31SKent Overstreet struct vm_area_struct;
16*6060ef31SKent Overstreet 
17af993f58SAndrei Vagin struct timens_offsets {
18af993f58SAndrei Vagin 	struct timespec64 monotonic;
19af993f58SAndrei Vagin 	struct timespec64 boottime;
20af993f58SAndrei Vagin };
21af993f58SAndrei Vagin 
22769071acSAndrei Vagin struct time_namespace {
23769071acSAndrei Vagin 	struct user_namespace	*user_ns;
24769071acSAndrei Vagin 	struct ucounts		*ucounts;
25769071acSAndrei Vagin 	struct ns_common	ns;
26af993f58SAndrei Vagin 	struct timens_offsets	offsets;
27afaa7b5aSDmitry Safonov 	struct page		*vvar_page;
28afaa7b5aSDmitry Safonov 	/* If set prevents changing offsets after any task joined namespace. */
29afaa7b5aSDmitry Safonov 	bool			frozen_offsets;
30769071acSAndrei Vagin } __randomize_layout;
31769071acSAndrei Vagin 
32769071acSAndrei Vagin extern struct time_namespace init_time_ns;
33769071acSAndrei Vagin 
34769071acSAndrei Vagin #ifdef CONFIG_TIME_NS
3570ddf651SDmitry Safonov extern int vdso_join_timens(struct task_struct *task,
3670ddf651SDmitry Safonov 			    struct time_namespace *ns);
3776c12881SChristian Brauner extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
3870ddf651SDmitry Safonov 
get_time_ns(struct time_namespace * ns)39769071acSAndrei Vagin static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
40769071acSAndrei Vagin {
4128c41efdSKirill Tkhai 	refcount_inc(&ns->ns.count);
42769071acSAndrei Vagin 	return ns;
43769071acSAndrei Vagin }
44769071acSAndrei Vagin 
45769071acSAndrei Vagin struct time_namespace *copy_time_ns(unsigned long flags,
46769071acSAndrei Vagin 				    struct user_namespace *user_ns,
47769071acSAndrei Vagin 				    struct time_namespace *old_ns);
4828c41efdSKirill Tkhai void free_time_ns(struct time_namespace *ns);
495c62634fSHui Su void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);
50d6c494e8SJann Horn struct page *find_timens_vvar_page(struct vm_area_struct *vma);
51769071acSAndrei Vagin 
put_time_ns(struct time_namespace * ns)52769071acSAndrei Vagin static inline void put_time_ns(struct time_namespace *ns)
53769071acSAndrei Vagin {
5428c41efdSKirill Tkhai 	if (refcount_dec_and_test(&ns->ns.count))
5528c41efdSKirill Tkhai 		free_time_ns(ns);
56769071acSAndrei Vagin }
57769071acSAndrei Vagin 
5804a8682aSAndrei Vagin void proc_timens_show_offsets(struct task_struct *p, struct seq_file *m);
5904a8682aSAndrei Vagin 
6004a8682aSAndrei Vagin struct proc_timens_offset {
6104a8682aSAndrei Vagin 	int			clockid;
6204a8682aSAndrei Vagin 	struct timespec64	val;
6304a8682aSAndrei Vagin };
6404a8682aSAndrei Vagin 
6504a8682aSAndrei Vagin int proc_timens_set_offset(struct file *file, struct task_struct *p,
6604a8682aSAndrei Vagin 			   struct proc_timens_offset *offsets, int n);
6704a8682aSAndrei Vagin 
timens_add_monotonic(struct timespec64 * ts)68af993f58SAndrei Vagin static inline void timens_add_monotonic(struct timespec64 *ts)
69af993f58SAndrei Vagin {
70af993f58SAndrei Vagin 	struct timens_offsets *ns_offsets = &current->nsproxy->time_ns->offsets;
71af993f58SAndrei Vagin 
72af993f58SAndrei Vagin 	*ts = timespec64_add(*ts, ns_offsets->monotonic);
73af993f58SAndrei Vagin }
74af993f58SAndrei Vagin 
timens_add_boottime(struct timespec64 * ts)75af993f58SAndrei Vagin static inline void timens_add_boottime(struct timespec64 *ts)
76af993f58SAndrei Vagin {
77af993f58SAndrei Vagin 	struct timens_offsets *ns_offsets = &current->nsproxy->time_ns->offsets;
78af993f58SAndrei Vagin 
79af993f58SAndrei Vagin 	*ts = timespec64_add(*ts, ns_offsets->boottime);
80af993f58SAndrei Vagin }
81af993f58SAndrei Vagin 
timens_add_boottime_ns(u64 nsec)8231909e33SMichael Weiß static inline u64 timens_add_boottime_ns(u64 nsec)
8331909e33SMichael Weiß {
8431909e33SMichael Weiß 	struct timens_offsets *ns_offsets = &current->nsproxy->time_ns->offsets;
8531909e33SMichael Weiß 
8631909e33SMichael Weiß 	return nsec + timespec64_to_ns(&ns_offsets->boottime);
8731909e33SMichael Weiß }
8831909e33SMichael Weiß 
timens_sub_boottime(struct timespec64 * ts)8931909e33SMichael Weiß static inline void timens_sub_boottime(struct timespec64 *ts)
9031909e33SMichael Weiß {
9131909e33SMichael Weiß 	struct timens_offsets *ns_offsets = &current->nsproxy->time_ns->offsets;
9231909e33SMichael Weiß 
9331909e33SMichael Weiß 	*ts = timespec64_sub(*ts, ns_offsets->boottime);
9431909e33SMichael Weiß }
9531909e33SMichael Weiß 
9689dd8eecSAndrei Vagin ktime_t do_timens_ktime_to_host(clockid_t clockid, ktime_t tim,
9789dd8eecSAndrei Vagin 				struct timens_offsets *offsets);
9889dd8eecSAndrei Vagin 
timens_ktime_to_host(clockid_t clockid,ktime_t tim)9989dd8eecSAndrei Vagin static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
10089dd8eecSAndrei Vagin {
10189dd8eecSAndrei Vagin 	struct time_namespace *ns = current->nsproxy->time_ns;
10289dd8eecSAndrei Vagin 
10389dd8eecSAndrei Vagin 	if (likely(ns == &init_time_ns))
10489dd8eecSAndrei Vagin 		return tim;
10589dd8eecSAndrei Vagin 
10689dd8eecSAndrei Vagin 	return do_timens_ktime_to_host(clockid, tim, &ns->offsets);
10789dd8eecSAndrei Vagin }
10889dd8eecSAndrei Vagin 
109769071acSAndrei Vagin #else
vdso_join_timens(struct task_struct * task,struct time_namespace * ns)11070ddf651SDmitry Safonov static inline int vdso_join_timens(struct task_struct *task,
11170ddf651SDmitry Safonov 				   struct time_namespace *ns)
11270ddf651SDmitry Safonov {
11370ddf651SDmitry Safonov 	return 0;
11470ddf651SDmitry Safonov }
11570ddf651SDmitry Safonov 
timens_commit(struct task_struct * tsk,struct time_namespace * ns)11676c12881SChristian Brauner static inline void timens_commit(struct task_struct *tsk,
11776c12881SChristian Brauner 				 struct time_namespace *ns)
11876c12881SChristian Brauner {
11976c12881SChristian Brauner }
12076c12881SChristian Brauner 
get_time_ns(struct time_namespace * ns)121769071acSAndrei Vagin static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
122769071acSAndrei Vagin {
123769071acSAndrei Vagin 	return NULL;
124769071acSAndrei Vagin }
125769071acSAndrei Vagin 
put_time_ns(struct time_namespace * ns)126769071acSAndrei Vagin static inline void put_time_ns(struct time_namespace *ns)
127769071acSAndrei Vagin {
128769071acSAndrei Vagin }
129769071acSAndrei Vagin 
130769071acSAndrei Vagin static inline
copy_time_ns(unsigned long flags,struct user_namespace * user_ns,struct time_namespace * old_ns)131769071acSAndrei Vagin struct time_namespace *copy_time_ns(unsigned long flags,
132769071acSAndrei Vagin 				    struct user_namespace *user_ns,
133769071acSAndrei Vagin 				    struct time_namespace *old_ns)
134769071acSAndrei Vagin {
135769071acSAndrei Vagin 	if (flags & CLONE_NEWTIME)
136769071acSAndrei Vagin 		return ERR_PTR(-EINVAL);
137769071acSAndrei Vagin 
138769071acSAndrei Vagin 	return old_ns;
139769071acSAndrei Vagin }
140769071acSAndrei Vagin 
timens_on_fork(struct nsproxy * nsproxy,struct task_struct * tsk)1415c62634fSHui Su static inline void timens_on_fork(struct nsproxy *nsproxy,
142769071acSAndrei Vagin 				 struct task_struct *tsk)
143769071acSAndrei Vagin {
1445c62634fSHui Su 	return;
145769071acSAndrei Vagin }
146769071acSAndrei Vagin 
find_timens_vvar_page(struct vm_area_struct * vma)147d6c494e8SJann Horn static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
148d6c494e8SJann Horn {
149d6c494e8SJann Horn 	return NULL;
150d6c494e8SJann Horn }
151d6c494e8SJann Horn 
timens_add_monotonic(struct timespec64 * ts)152af993f58SAndrei Vagin static inline void timens_add_monotonic(struct timespec64 *ts) { }
timens_add_boottime(struct timespec64 * ts)153af993f58SAndrei Vagin static inline void timens_add_boottime(struct timespec64 *ts) { }
15431909e33SMichael Weiß 
timens_add_boottime_ns(u64 nsec)15531909e33SMichael Weiß static inline u64 timens_add_boottime_ns(u64 nsec)
15631909e33SMichael Weiß {
15731909e33SMichael Weiß 	return nsec;
15831909e33SMichael Weiß }
15931909e33SMichael Weiß 
timens_sub_boottime(struct timespec64 * ts)16031909e33SMichael Weiß static inline void timens_sub_boottime(struct timespec64 *ts) { }
16131909e33SMichael Weiß 
timens_ktime_to_host(clockid_t clockid,ktime_t tim)16289dd8eecSAndrei Vagin static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
16389dd8eecSAndrei Vagin {
16489dd8eecSAndrei Vagin 	return tim;
16589dd8eecSAndrei Vagin }
166769071acSAndrei Vagin #endif
167769071acSAndrei Vagin 
168769071acSAndrei Vagin #endif /* _LINUX_TIMENS_H */
169