On 12/13, Eric W. Biederman wrote:
>
> Oleg Nesterov <o...@redhat.com> writes:
>
> > In this case current->group_leader or parent/real_parent can point to the
> > exited/freed tasks. I already said this many times, ee really need to 
> > nullify
> > them in __unhash_process() but this needs a lot of (mostly simple)
> > cleanups.
>
> Is there anything wrong with starting with the patch below?
>
> diff --git a/kernel/exit.c b/kernel/exit.c
> index 9d68c45ebbe3..03daeecc335d 100644
> --- a/kernel/exit.c
> +++ b/kernel/exit.c
> @@ -200,6 +200,7 @@ void release_task(struct task_struct *p)
>                 if (zap_leader)
>                         leader->exit_state = EXIT_DEAD;
>         }
> +       p->group_leader = NULL;

Yes, see above, this is what we should do. Except I think we should
change __unhash_process() to do this. The same for parent/real_parent.

> That seems to cut to the heart of the matter.

Exactly.

But we can not start with this change. Just for example,
task_session/task_pgrp/tgid can obviously crash, even if used properly,
they will need to check group_leader != NULL. __task_pid_nr_ns() should
be changed too. And more.

That is why I'd prefer to start with the simple fix I suggested before,
then do the cleanups.

And imo that change makes sense in any case to avoid the code duplication,
even if we change __unhash_process() to nullify group_leader/etc. Note that
we can also add __PIDTYPE_PPID and turn task_ppid_nr_ns() into another
trivial users of  __task_pid_nr_ns(). Just it will need to check task != NULL
instead if pid_alive(p).

So, will you agree with v2 below? s/PIDTYPE_TGID/__PIDTYPE_TGID/ as you
suggested, and move task_tgid_nr_ns() into sched.h close to other similar
helpers.

Oleg.


--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -8,7 +8,9 @@ enum pid_type
        PIDTYPE_PID,
        PIDTYPE_PGID,
        PIDTYPE_SID,
-       PIDTYPE_MAX
+       PIDTYPE_MAX,
+       /* only valid to __task_pid_nr_ns() */
+       __PIDTYPE_TGID
 };
 
 /*
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2117,14 +2117,6 @@ static inline pid_t task_tgid_nr(struct task_struct *tsk)
        return tsk->tgid;
 }
 
-pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
-
-static inline pid_t task_tgid_vnr(struct task_struct *tsk)
-{
-       return pid_vnr(task_tgid(tsk));
-}
-
-
 static inline int pid_alive(const struct task_struct *p);
 static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct 
pid_namespace *ns)
 {
@@ -2166,6 +2158,16 @@ static inline pid_t task_session_vnr(struct task_struct 
*tsk)
        return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL);
 }
 
+static inline pid_t task_tgid_nr_ns(struct task_struct *tsk, struct 
pid_namespace *ns)
+{
+       return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, ns);
+}
+
+static inline pid_t task_tgid_vnr(struct task_struct *tsk)
+{
+       return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, NULL);
+}
+
 /* obsolete, do not use */
 static inline pid_t task_pgrp_nr(struct task_struct *tsk)
 {
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -526,8 +526,11 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum 
pid_type type,
        if (!ns)
                ns = task_active_pid_ns(current);
        if (likely(pid_alive(task))) {
-               if (type != PIDTYPE_PID)
+               if (type != PIDTYPE_PID) {
+                       if (type == __PIDTYPE_TGID)
+                               type = PIDTYPE_PID;
                        task = task->group_leader;
+               }
                nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns);
        }
        rcu_read_unlock();
@@ -536,12 +539,6 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum 
pid_type type,
 }
 EXPORT_SYMBOL(__task_pid_nr_ns);
 
-pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
-{
-       return pid_nr_ns(task_tgid(tsk), ns);
-}
-EXPORT_SYMBOL(task_tgid_nr_ns);
-
 struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
 {
        return ns_of_pid(task_pid(tsk));

Reply via email to