posix-cpu-timers: Move state tracking to struct posix_cputimers
[sfrench/cifs-2.6.git] / kernel / fork.c
index dfa78985a6fd50fef36fac24a091eb20563fd716..f1228d9f0b11747ca1b030cb831ecb0863e7af9c 100644 (file)
@@ -1517,28 +1517,17 @@ void __cleanup_sighand(struct sighand_struct *sighand)
        }
 }
 
-#ifdef CONFIG_POSIX_TIMERS
 /*
  * Initialize POSIX timer handling for a thread group.
  */
 static void posix_cpu_timers_init_group(struct signal_struct *sig)
 {
+       struct posix_cputimers *pct = &sig->posix_cputimers;
        unsigned long cpu_limit;
 
        cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
-       if (cpu_limit != RLIM_INFINITY) {
-               sig->cputime_expires.prof_exp = cpu_limit * NSEC_PER_SEC;
-               sig->cputimer.running = true;
-       }
-
-       /* The timer lists. */
-       INIT_LIST_HEAD(&sig->cpu_timers[0]);
-       INIT_LIST_HEAD(&sig->cpu_timers[1]);
-       INIT_LIST_HEAD(&sig->cpu_timers[2]);
+       posix_cputimers_group_init(pct, cpu_limit);
 }
-#else
-static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
-#endif
 
 static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 {
@@ -1640,23 +1629,6 @@ static void rt_mutex_init_task(struct task_struct *p)
 #endif
 }
 
-#ifdef CONFIG_POSIX_TIMERS
-/*
- * Initialize POSIX timer handling for a single task.
- */
-static void posix_cpu_timers_init(struct task_struct *tsk)
-{
-       tsk->cputime_expires.prof_exp = 0;
-       tsk->cputime_expires.virt_exp = 0;
-       tsk->cputime_expires.sched_exp = 0;
-       INIT_LIST_HEAD(&tsk->cpu_timers[0]);
-       INIT_LIST_HEAD(&tsk->cpu_timers[1]);
-       INIT_LIST_HEAD(&tsk->cpu_timers[2]);
-}
-#else
-static inline void posix_cpu_timers_init(struct task_struct *tsk) { }
-#endif
-
 static inline void init_task_pid_links(struct task_struct *task)
 {
        enum pid_type type;
@@ -1935,7 +1907,7 @@ static __latent_entropy struct task_struct *copy_process(
        task_io_accounting_init(&p->ioac);
        acct_clear_integrals(p);
 
-       posix_cpu_timers_init(p);
+       posix_cputimers_init(&p->posix_cputimers);
 
        p->io_context = NULL;
        audit_set_context(p, NULL);
@@ -2405,6 +2377,16 @@ long _do_fork(struct kernel_clone_args *args)
        return nr;
 }
 
+bool legacy_clone_args_valid(const struct kernel_clone_args *kargs)
+{
+       /* clone(CLONE_PIDFD) uses parent_tidptr to return a pidfd */
+       if ((kargs->flags & CLONE_PIDFD) &&
+           (kargs->flags & CLONE_PARENT_SETTID))
+               return false;
+
+       return true;
+}
+
 #ifndef CONFIG_HAVE_COPY_THREAD_TLS
 /* For compatibility with architectures that call do_fork directly rather than
  * using the syscall entry points below. */
@@ -2416,6 +2398,7 @@ long do_fork(unsigned long clone_flags,
 {
        struct kernel_clone_args args = {
                .flags          = (clone_flags & ~CSIGNAL),
+               .pidfd          = parent_tidptr,
                .child_tid      = child_tidptr,
                .parent_tid     = parent_tidptr,
                .exit_signal    = (clone_flags & CSIGNAL),
@@ -2423,6 +2406,9 @@ long do_fork(unsigned long clone_flags,
                .stack_size     = stack_size,
        };
 
+       if (!legacy_clone_args_valid(&args))
+               return -EINVAL;
+
        return _do_fork(&args);
 }
 #endif
@@ -2504,8 +2490,7 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                .tls            = tls,
        };
 
-       /* clone(CLONE_PIDFD) uses parent_tidptr to return a pidfd */
-       if ((clone_flags & CLONE_PIDFD) && (clone_flags & CLONE_PARENT_SETTID))
+       if (!legacy_clone_args_valid(&args))
                return -EINVAL;
 
        return _do_fork(&args);