diff options
author | Oleg Nesterov <oleg@redhat.com> | 2017-08-21 11:35:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-08-21 15:47:31 -0400 |
commit | dd1c1f2f2028a7b851f701fc6a8ebe39dcb95e7c (patch) | |
tree | 96b5e5466504cc8c88b0f0435e80f70f0c627c58 | |
parent | 14ccee78fc82f5512908f4424f541549a5705b89 (diff) |
pids: make task_tgid_nr_ns() safe
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>
-rw-r--r-- | include/linux/pid.h | 4 | ||||
-rw-r--r-- | include/linux/sched.h | 51 | ||||
-rw-r--r-- | kernel/pid.c | 11 |
3 files changed, 34 insertions, 32 deletions
diff --git a/include/linux/pid.h b/include/linux/pid.h index 4d179316e431..719582744a2e 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 8337e2db0bb2..c05ac5f5aa03 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1163,13 +1163,6 @@ static inline pid_t task_tgid_nr(struct task_struct *tsk) | |||
1163 | return tsk->tgid; | 1163 | return tsk->tgid; |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | extern pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns); | ||
1167 | |||
1168 | static inline pid_t task_tgid_vnr(struct task_struct *tsk) | ||
1169 | { | ||
1170 | return pid_vnr(task_tgid(tsk)); | ||
1171 | } | ||
1172 | |||
1173 | /** | 1166 | /** |
1174 | * pid_alive - check that a task structure is not stale | 1167 | * pid_alive - check that a task structure is not stale |
1175 | * @p: Task structure to be checked. | 1168 | * @p: Task structure to be checked. |
@@ -1185,23 +1178,6 @@ static inline int pid_alive(const struct task_struct *p) | |||
1185 | return p->pids[PIDTYPE_PID].pid != NULL; | 1178 | return p->pids[PIDTYPE_PID].pid != NULL; |
1186 | } | 1179 | } |
1187 | 1180 | ||
1188 | static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) | ||
1189 | { | ||
1190 | pid_t pid = 0; | ||
1191 | |||
1192 | rcu_read_lock(); | ||
1193 | if (pid_alive(tsk)) | ||
1194 | pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns); | ||
1195 | rcu_read_unlock(); | ||
1196 | |||
1197 | return pid; | ||
1198 | } | ||
1199 | |||
1200 | static inline pid_t task_ppid_nr(const struct task_struct *tsk) | ||
1201 | { | ||
1202 | return task_ppid_nr_ns(tsk, &init_pid_ns); | ||
1203 | } | ||
1204 | |||
1205 | static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) | 1181 | static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) |
1206 | { | 1182 | { |
1207 | return __task_pid_nr_ns(tsk, PIDTYPE_PGID, ns); | 1183 | return __task_pid_nr_ns(tsk, PIDTYPE_PGID, ns); |
@@ -1223,6 +1199,33 @@ static inline pid_t task_session_vnr(struct task_struct *tsk) | |||
1223 | return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL); | 1199 | return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL); |
1224 | } | 1200 | } |
1225 | 1201 | ||
1202 | static inline pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) | ||
1203 | { | ||
1204 | return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, ns); | ||
1205 | } | ||
1206 | |||
1207 | static inline pid_t task_tgid_vnr(struct task_struct *tsk) | ||
1208 | { | ||
1209 | return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, NULL); | ||
1210 | } | ||
1211 | |||
1212 | static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) | ||
1213 | { | ||
1214 | pid_t pid = 0; | ||
1215 | |||
1216 | rcu_read_lock(); | ||
1217 | if (pid_alive(tsk)) | ||
1218 | pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns); | ||
1219 | rcu_read_unlock(); | ||
1220 | |||
1221 | return pid; | ||
1222 | } | ||
1223 | |||
1224 | static inline pid_t task_ppid_nr(const struct task_struct *tsk) | ||
1225 | { | ||
1226 | return task_ppid_nr_ns(tsk, &init_pid_ns); | ||
1227 | } | ||
1228 | |||
1226 | /* Obsolete, do not use: */ | 1229 | /* Obsolete, do not use: */ |
1227 | static inline pid_t task_pgrp_nr(struct task_struct *tsk) | 1230 | static inline pid_t task_pgrp_nr(struct task_struct *tsk) |
1228 | { | 1231 | { |
diff --git a/kernel/pid.c b/kernel/pid.c index c69c30d827e5..020dedbdf066 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -527,8 +527,11 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, | |||
527 | if (!ns) | 527 | if (!ns) |
528 | ns = task_active_pid_ns(current); | 528 | ns = task_active_pid_ns(current); |
529 | if (likely(pid_alive(task))) { | 529 | if (likely(pid_alive(task))) { |
530 | if (type != PIDTYPE_PID) | 530 | if (type != PIDTYPE_PID) { |
531 | if (type == __PIDTYPE_TGID) | ||
532 | type = PIDTYPE_PID; | ||
531 | task = task->group_leader; | 533 | task = task->group_leader; |
534 | } | ||
532 | nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns); | 535 | nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns); |
533 | } | 536 | } |
534 | rcu_read_unlock(); | 537 | rcu_read_unlock(); |
@@ -537,12 +540,6 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, | |||
537 | } | 540 | } |
538 | EXPORT_SYMBOL(__task_pid_nr_ns); | 541 | EXPORT_SYMBOL(__task_pid_nr_ns); |
539 | 542 | ||
540 | pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) | ||
541 | { | ||
542 | return pid_nr_ns(task_tgid(tsk), ns); | ||
543 | } | ||
544 | EXPORT_SYMBOL(task_tgid_nr_ns); | ||
545 | |||
546 | struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) | 543 | struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) |
547 | { | 544 | { |
548 | return ns_of_pid(task_pid(tsk)); | 545 | return ns_of_pid(task_pid(tsk)); |