linux/kernel/time/namespace.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Author: Andrei Vagin <[email protected]>
 * Author: Dmitry Safonov <[email protected]>
 */

#include <linux/time_namespace.h>
#include <linux/user_namespace.h>
#include <linux/sched/signal.h>
#include <linux/sched/task.h>
#include <linux/clocksource.h>
#include <linux/seq_file.h>
#include <linux/proc_ns.h>
#include <linux/export.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/cred.h>
#include <linux/err.h>
#include <linux/mm.h>

#include <vdso/datapage.h>

ktime_t do_timens_ktime_to_host(clockid_t clockid, ktime_t tim,
				struct timens_offsets *ns_offsets)
{}

static struct ucounts *inc_time_namespaces(struct user_namespace *ns)
{}

static void dec_time_namespaces(struct ucounts *ucounts)
{}

/**
 * clone_time_ns - Clone a time namespace
 * @user_ns:	User namespace which owns a new namespace.
 * @old_ns:	Namespace to clone
 *
 * Clone @old_ns and set the clone refcount to 1
 *
 * Return: The new namespace or ERR_PTR.
 */
static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
					  struct time_namespace *old_ns)
{}

/**
 * copy_time_ns - Create timens_for_children from @old_ns
 * @flags:	Cloning flags
 * @user_ns:	User namespace which owns a new namespace.
 * @old_ns:	Namespace to clone
 *
 * If CLONE_NEWTIME specified in @flags, creates a new timens_for_children;
 * adds a refcounter to @old_ns otherwise.
 *
 * Return: timens_for_children namespace or ERR_PTR.
 */
struct time_namespace *copy_time_ns(unsigned long flags,
	struct user_namespace *user_ns, struct time_namespace *old_ns)
{}

static struct timens_offset offset_from_ts(struct timespec64 off)
{}

/*
 * A time namespace VVAR page has the same layout as the VVAR page which
 * contains the system wide VDSO data.
 *
 * For a normal task the VVAR pages are installed in the normal ordering:
 *     VVAR
 *     PVCLOCK
 *     HVCLOCK
 *     TIMENS   <- Not really required
 *
 * Now for a timens task the pages are installed in the following order:
 *     TIMENS
 *     PVCLOCK
 *     HVCLOCK
 *     VVAR
 *
 * The check for vdso_data->clock_mode is in the unlikely path of
 * the seq begin magic. So for the non-timens case most of the time
 * 'seq' is even, so the branch is not taken.
 *
 * If 'seq' is odd, i.e. a concurrent update is in progress, the extra check
 * for vdso_data->clock_mode is a non-issue. The task is spin waiting for the
 * update to finish and for 'seq' to become even anyway.
 *
 * Timens page has vdso_data->clock_mode set to VDSO_CLOCKMODE_TIMENS which
 * enforces the time namespace handling path.
 */
static void timens_setup_vdso_data(struct vdso_data *vdata,
				   struct time_namespace *ns)
{}

struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{}

/*
 * Protects possibly multiple offsets writers racing each other
 * and tasks entering the namespace.
 */
static DEFINE_MUTEX(offset_lock);

static void timens_set_vvar_page(struct task_struct *task,
				struct time_namespace *ns)
{}

void free_time_ns(struct time_namespace *ns)
{}

static struct time_namespace *to_time_ns(struct ns_common *ns)
{}

static struct ns_common *timens_get(struct task_struct *task)
{}

static struct ns_common *timens_for_children_get(struct task_struct *task)
{}

static void timens_put(struct ns_common *ns)
{}

void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
{}

static int timens_install(struct nsset *nsset, struct ns_common *new)
{}

void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk)
{}

static struct user_namespace *timens_owner(struct ns_common *ns)
{}

static void show_offset(struct seq_file *m, int clockid, struct timespec64 *ts)
{}

void proc_timens_show_offsets(struct task_struct *p, struct seq_file *m)
{}

int proc_timens_set_offset(struct file *file, struct task_struct *p,
			   struct proc_timens_offset *offsets, int noffsets)
{}

const struct proc_ns_operations timens_operations =;

const struct proc_ns_operations timens_for_children_operations =;

struct time_namespace init_time_ns =;