aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov2017-08-21 10:35:02 -0500
committerGreg Kroah-Hartman2017-08-24 19:02:36 -0500
commitb4cf49024cf412a94121e61f8056636c557ead98 (patch)
tree38a9cdf76224f841d41faff29b57a51a90e6c3c4
parent46d51a26efbc7cbaa2bc1f01628a00a604193856 (diff)
downloadkernel-omap-b4cf49024cf412a94121e61f8056636c557ead98.tar.gz
kernel-omap-b4cf49024cf412a94121e61f8056636c557ead98.tar.xz
kernel-omap-b4cf49024cf412a94121e61f8056636c557ead98.zip
pids: make task_tgid_nr_ns() safe
commit dd1c1f2f2028a7b851f701fc6a8ebe39dcb95e7c upstream. This was reported many times, and this was even mentioned in commit 52ee2dfdd4f5 ("pids: refactor vnr/nr_ns helpers to make them safe") but somehow nobody bothered to fix the obvious problem: task_tgid_nr_ns() is not safe because task->group_leader points to nowhere after the exiting task passes exit_notify(), rcu_read_lock() can not help. We really need to change __unhash_process() to nullify group_leader, parent, and real_parent, but this needs some cleanups. Until then we can turn task_tgid_nr_ns() into another user of __task_pid_nr_ns() and fix the problem. Reported-by: Troy Kensinger <tkensinger@google.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--include/linux/pid.h4
-rw-r--r--include/linux/sched.h50
-rw-r--r--kernel/pid.c11
3 files changed, 34 insertions, 31 deletions
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 23705a53abba..97b745ddece5 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -8,7 +8,9 @@ enum pid_type
8 PIDTYPE_PID, 8 PIDTYPE_PID,
9 PIDTYPE_PGID, 9 PIDTYPE_PGID,
10 PIDTYPE_SID, 10 PIDTYPE_SID,
11 PIDTYPE_MAX 11 PIDTYPE_MAX,
12 /* only valid to __task_pid_nr_ns() */
13 __PIDTYPE_TGID
12}; 14};
13 15
14/* 16/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index eff7c1fad26f..e887c8d6f395 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1949,31 +1949,8 @@ static inline pid_t task_tgid_nr(struct task_struct *tsk)
1949 return tsk->tgid; 1949 return tsk->tgid;
1950} 1950}
1951 1951
1952pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
1953
1954static inline pid_t task_tgid_vnr(struct task_struct *tsk)
1955{
1956 return pid_vnr(task_tgid(tsk));
1957}
1958
1959 1952
1960static inline int pid_alive(const struct task_struct *p); 1953static inline int pid_alive(const struct task_struct *p);
1961static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns)
1962{
1963 pid_t pid = 0;
1964
1965 rcu_read_lock();
1966 if (pid_alive(tsk))
1967 pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns);
1968 rcu_read_unlock();
1969
1970 return pid;
1971}
1972
1973static inline pid_t task_ppid_nr(const struct task_struct *tsk)
1974{
1975 return task_ppid_nr_ns(tsk, &init_pid_ns);
1976}
1977 1954
1978static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, 1955static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk,
1979 struct pid_namespace *ns) 1956 struct pid_namespace *ns)
@@ -1998,6 +1975,33 @@ static inline pid_t task_session_vnr(struct task_struct *tsk)
1998 return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL); 1975 return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL);
1999} 1976}
2000 1977
1978static inline pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
1979{
1980 return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, ns);
1981}
1982
1983static inline pid_t task_tgid_vnr(struct task_struct *tsk)
1984{
1985 return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, NULL);
1986}
1987
1988static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns)
1989{
1990 pid_t pid = 0;
1991
1992 rcu_read_lock();
1993 if (pid_alive(tsk))
1994 pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns);
1995 rcu_read_unlock();
1996
1997 return pid;
1998}
1999
2000static inline pid_t task_ppid_nr(const struct task_struct *tsk)
2001{
2002 return task_ppid_nr_ns(tsk, &init_pid_ns);
2003}
2004
2001/* obsolete, do not use */ 2005/* obsolete, do not use */
2002static inline pid_t task_pgrp_nr(struct task_struct *tsk) 2006static inline pid_t task_pgrp_nr(struct task_struct *tsk)
2003{ 2007{
diff --git a/kernel/pid.c b/kernel/pid.c
index 78b3d9f80d44..b17263be9082 100644
--- 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,
526 if (!ns) 526 if (!ns)
527 ns = task_active_pid_ns(current); 527 ns = task_active_pid_ns(current);
528 if (likely(pid_alive(task))) { 528 if (likely(pid_alive(task))) {
529 if (type != PIDTYPE_PID) 529 if (type != PIDTYPE_PID) {
530 if (type == __PIDTYPE_TGID)
531 type = PIDTYPE_PID;
530 task = task->group_leader; 532 task = task->group_leader;
533 }
531 nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns); 534 nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns);
532 } 535 }
533 rcu_read_unlock(); 536 rcu_read_unlock();
@@ -536,12 +539,6 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
536} 539}
537EXPORT_SYMBOL(__task_pid_nr_ns); 540EXPORT_SYMBOL(__task_pid_nr_ns);
538 541
539pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
540{
541 return pid_nr_ns(task_tgid(tsk), ns);
542}
543EXPORT_SYMBOL(task_tgid_nr_ns);
544
545struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) 542struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
546{ 543{
547 return ns_of_pid(task_pid(tsk)); 544 return ns_of_pid(task_pid(tsk));