lkml.org 
[lkml]   [2020]   [Mar]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 1/4] ns: prepare time namespace for clone3()
    Date
    To enable clone3()ing a process directly into a new time namespace with
    a clock offset, this changes the time namespace code by renaming the
    variable proc_timens_offset (which was used to set a timens offset via
    /proc) to set_timens_offset to avoid confusion why it will be used in
    clone3() without being related to /proc.

    This also moves out the code of actually setting the clock offsets to
    its own function to be later used via clone3().

    Signed-off-by: Adrian Reber <areber@redhat.com>
    ---
    fs/proc/base.c | 4 +-
    include/linux/time_namespace.h | 16 +++--
    kernel/time/namespace.c | 126 +++++++++++++++++----------------
    3 files changed, 78 insertions(+), 68 deletions(-)

    diff --git a/fs/proc/base.c b/fs/proc/base.c
    index c7c64272b0fa..2ca68f11ff0e 100644
    --- a/fs/proc/base.c
    +++ b/fs/proc/base.c
    @@ -1554,7 +1554,7 @@ static ssize_t timens_offsets_write(struct file *file, const char __user *buf,
    size_t count, loff_t *ppos)
    {
    struct inode *inode = file_inode(file);
    - struct proc_timens_offset offsets[2];
    + struct set_timens_offset offsets[2];
    char *kbuf = NULL, *pos, *next_line;
    struct task_struct *p;
    int ret, noffsets;
    @@ -1572,7 +1572,7 @@ static ssize_t timens_offsets_write(struct file *file, const char __user *buf,
    ret = -EINVAL;
    noffsets = 0;
    for (pos = kbuf; pos; pos = next_line) {
    - struct proc_timens_offset *off = &offsets[noffsets];
    + struct set_timens_offset *off = &offsets[noffsets];
    int err;

    /* Find the end of line and ensure we don't look past it */
    diff --git a/include/linux/time_namespace.h b/include/linux/time_namespace.h
    index 824d54e057eb..fb4ca4402a2a 100644
    --- a/include/linux/time_namespace.h
    +++ b/include/linux/time_namespace.h
    @@ -30,6 +30,15 @@ struct time_namespace {

    extern struct time_namespace init_time_ns;

    +/*
    + * This structure is used to set the time namespace offset
    + * via /proc as well as via clone3().
    + */
    +struct set_timens_offset {
    + int clockid;
    + struct timespec64 val;
    +};
    +
    #ifdef CONFIG_TIME_NS
    extern int vdso_join_timens(struct task_struct *task,
    struct time_namespace *ns);
    @@ -54,13 +63,8 @@ static inline void put_time_ns(struct time_namespace *ns)

    void proc_timens_show_offsets(struct task_struct *p, struct seq_file *m);

    -struct proc_timens_offset {
    - int clockid;
    - struct timespec64 val;
    -};
    -
    int proc_timens_set_offset(struct file *file, struct task_struct *p,
    - struct proc_timens_offset *offsets, int n);
    + struct set_timens_offset *offsets, int n);

    static inline void timens_add_monotonic(struct timespec64 *ts)
    {
    diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
    index 12858507d75a..839efa7c6886 100644
    --- a/kernel/time/namespace.c
    +++ b/kernel/time/namespace.c
    @@ -307,6 +307,69 @@ static int timens_install(struct nsproxy *nsproxy, struct ns_common *new)
    return 0;
    }

    +static int timens_set_offset(struct task_struct *p, struct time_namespace *ns,
    + struct set_timens_offset *offsets, int noffsets)
    +{
    + struct timespec64 tp;
    + int i, err;
    +
    + for (i = 0; i < noffsets; i++) {
    + struct set_timens_offset *off = &offsets[i];
    +
    + switch (off->clockid) {
    + case CLOCK_MONOTONIC:
    + ktime_get_ts64(&tp);
    + break;
    + case CLOCK_BOOTTIME:
    + ktime_get_boottime_ts64(&tp);
    + break;
    + default:
    + return -EINVAL;
    + }
    +
    + if (off->val.tv_sec > KTIME_SEC_MAX ||
    + off->val.tv_sec < -KTIME_SEC_MAX)
    + return -ERANGE;
    +
    + tp = timespec64_add(tp, off->val);
    + /*
    + * KTIME_SEC_MAX is divided by 2 to be sure that KTIME_MAX is
    + * still unreachable.
    + */
    + if (tp.tv_sec < 0 || tp.tv_sec > KTIME_SEC_MAX / 2)
    + return -ERANGE;
    + }
    +
    + mutex_lock(&offset_lock);
    + if (ns->frozen_offsets) {
    + err = -EACCES;
    + goto out_unlock;
    + }
    +
    + err = 0;
    + /* Don't report errors after this line */
    + for (i = 0; i < noffsets; i++) {
    + struct set_timens_offset *off = &offsets[i];
    + struct timespec64 *offset = NULL;
    +
    + switch (off->clockid) {
    + case CLOCK_MONOTONIC:
    + offset = &ns->offsets.monotonic;
    + break;
    + case CLOCK_BOOTTIME:
    + offset = &ns->offsets.boottime;
    + break;
    + }
    +
    + *offset = off->val;
    + }
    +
    +out_unlock:
    + mutex_unlock(&offset_lock);
    +
    + return err;
    +}
    +
    int timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk)
    {
    struct ns_common *nsc = &nsproxy->time_ns_for_children->ns;
    @@ -356,12 +419,11 @@ 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)
    + struct set_timens_offset *offsets, int noffsets)
    {
    struct ns_common *ns;
    struct time_namespace *time_ns;
    - struct timespec64 tp;
    - int i, err;
    + int err;

    ns = timens_for_children_get(p);
    if (!ns)
    @@ -373,63 +435,7 @@ int proc_timens_set_offset(struct file *file, struct task_struct *p,
    return -EPERM;
    }

    - for (i = 0; i < noffsets; i++) {
    - struct proc_timens_offset *off = &offsets[i];
    -
    - switch (off->clockid) {
    - case CLOCK_MONOTONIC:
    - ktime_get_ts64(&tp);
    - break;
    - case CLOCK_BOOTTIME:
    - ktime_get_boottime_ts64(&tp);
    - break;
    - default:
    - err = -EINVAL;
    - goto out;
    - }
    -
    - err = -ERANGE;
    -
    - if (off->val.tv_sec > KTIME_SEC_MAX ||
    - off->val.tv_sec < -KTIME_SEC_MAX)
    - goto out;
    -
    - tp = timespec64_add(tp, off->val);
    - /*
    - * KTIME_SEC_MAX is divided by 2 to be sure that KTIME_MAX is
    - * still unreachable.
    - */
    - if (tp.tv_sec < 0 || tp.tv_sec > KTIME_SEC_MAX / 2)
    - goto out;
    - }
    -
    - mutex_lock(&offset_lock);
    - if (time_ns->frozen_offsets) {
    - err = -EACCES;
    - goto out_unlock;
    - }
    -
    - err = 0;
    - /* Don't report errors after this line */
    - for (i = 0; i < noffsets; i++) {
    - struct proc_timens_offset *off = &offsets[i];
    - struct timespec64 *offset = NULL;
    -
    - switch (off->clockid) {
    - case CLOCK_MONOTONIC:
    - offset = &time_ns->offsets.monotonic;
    - break;
    - case CLOCK_BOOTTIME:
    - offset = &time_ns->offsets.boottime;
    - break;
    - }
    -
    - *offset = off->val;
    - }
    -
    -out_unlock:
    - mutex_unlock(&offset_lock);
    -out:
    + err = timens_set_offset(p, time_ns, offsets, noffsets);
    put_time_ns(time_ns);

    return err;
    base-commit: 8b614cb8f1dcac8ca77cf4dd85f46ef3055f8238
    --
    2.24.1

    \
     
     \ /
      Last update: 2020-03-17 09:34    [W:7.164 / U:0.688 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site