* [PATCH 1/5] posix-cpu-timers: cpu_clock_sample_group no longer needs siglock
2020-02-28 17:07 [PATCH 0/5] posix-cpu-timers: Graceful handling of reaped processes Eric W. Biederman
@ 2020-02-28 17:08 ` Eric W. Biederman
2020-03-01 10:27 ` [tip: timers/core] posix-cpu-timers: cpu_clock_sample_group() " tip-bot2 for Eric W. Biederman
2020-02-28 17:09 ` [PATCH 2/5] posix-cpu-timers: Remove unnecessary locking around cpu_clock_sample_group Eric W. Biederman
` (3 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Eric W. Biederman @ 2020-02-28 17:08 UTC (permalink / raw)
To: linux-kernel; +Cc: Oleg Nesterov, Thomas Gleixner
As of e78c3496790e ("time, signal: Protect resource use statistics
with seqlock") cpu_clock_sample_group no longers needs siglock
protection so remove the stale comment.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
kernel/time/posix-cpu-timers.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 8ff6da77a01f..46cc188bf5ab 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -336,9 +336,7 @@ static void __thread_group_cputime(struct task_struct *tsk, u64 *samples)
/*
* Sample a process (thread group) clock for the given task clkid. If the
* group's cputime accounting is already enabled, read the atomic
- * store. Otherwise a full update is required. Task's sighand lock must be
- * held to protect the task traversal on a full update. clkid is already
- * validated.
+ * store. Otherwise a full update is required. clkid is already validated.
*/
static u64 cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
bool start)
--
2.25.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [tip: timers/core] posix-cpu-timers: cpu_clock_sample_group() no longer needs siglock
2020-02-28 17:08 ` [PATCH 1/5] posix-cpu-timers: cpu_clock_sample_group no longer needs siglock Eric W. Biederman
@ 2020-03-01 10:27 ` tip-bot2 for Eric W. Biederman
0 siblings, 0 replies; 13+ messages in thread
From: tip-bot2 for Eric W. Biederman @ 2020-03-01 10:27 UTC (permalink / raw)
To: linux-tip-commits; +Cc: Eric W. Biederman, Thomas Gleixner, x86, LKML
The following commit has been merged into the timers/core branch of tip:
Commit-ID: a2efdbf4fcb38ec1ae99c9d54d52c34fa867dc71
Gitweb: https://git.kernel.org/tip/a2efdbf4fcb38ec1ae99c9d54d52c34fa867dc71
Author: Eric W. Biederman <ebiederm@xmission.com>
AuthorDate: Fri, 28 Feb 2020 11:08:45 -06:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 01 Mar 2020 11:21:43 +01:00
posix-cpu-timers: cpu_clock_sample_group() no longer needs siglock
As of e78c3496790e ("time, signal: Protect resource use statistics with
seqlock") cpu_clock_sample_group() no longer needs siglock protection so
remove the stale comment.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/87eeuevduq.fsf@x220.int.ebiederm.org
---
kernel/time/posix-cpu-timers.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 8ff6da7..46cc188 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -336,9 +336,7 @@ static void __thread_group_cputime(struct task_struct *tsk, u64 *samples)
/*
* Sample a process (thread group) clock for the given task clkid. If the
* group's cputime accounting is already enabled, read the atomic
- * store. Otherwise a full update is required. Task's sighand lock must be
- * held to protect the task traversal on a full update. clkid is already
- * validated.
+ * store. Otherwise a full update is required. clkid is already validated.
*/
static u64 cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
bool start)
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/5] posix-cpu-timers: Remove unnecessary locking around cpu_clock_sample_group
2020-02-28 17:07 [PATCH 0/5] posix-cpu-timers: Graceful handling of reaped processes Eric W. Biederman
2020-02-28 17:08 ` [PATCH 1/5] posix-cpu-timers: cpu_clock_sample_group no longer needs siglock Eric W. Biederman
@ 2020-02-28 17:09 ` Eric W. Biederman
2020-03-01 10:27 ` [tip: timers/core] " tip-bot2 for Eric W. Biederman
2020-02-28 17:09 ` [PATCH 3/5] posix-cpu-timers: Pass the task into arm_timer Eric W. Biederman
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Eric W. Biederman @ 2020-02-28 17:09 UTC (permalink / raw)
To: linux-kernel; +Cc: Oleg Nesterov, Thomas Gleixner
As of e78c3496790e ("time, signal: Protect resource use statistics
with seqlock") cpu_clock_sample_group no longers needs siglock
protection. Unfortunately no one realized it at the time.
Remove the extra locking that is for cpu_clock_sample_group and not
for cpu_clock_sample. This significantly simplifies the code.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
kernel/time/posix-cpu-timers.c | 55 +++++-----------------------------
1 file changed, 7 insertions(+), 48 deletions(-)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 46cc188bf5ab..3b27710f9505 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -721,27 +721,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
now = cpu_clock_sample(clkid, p);
} else {
- struct sighand_struct *sighand;
- unsigned long flags;
-
- /*
- * Protect against sighand release/switch in exit/exec and
- * also make timer sampling safe if it ends up calling
- * thread_group_cputime().
- */
- sighand = lock_task_sighand(p, &flags);
- if (unlikely(sighand == NULL)) {
- /*
- * The process has been reaped.
- * We can't even collect a sample any more.
- * Disarm the timer, nothing else to do.
- */
- cpu_timer_setexpires(ctmr, 0);
- return;
- } else {
- now = cpu_clock_sample_group(clkid, p, false);
- unlock_task_sighand(p, &flags);
- }
+ now = cpu_clock_sample_group(clkid, p, false);
}
if (now < expires) {
@@ -988,41 +968,20 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
*/
if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
now = cpu_clock_sample(clkid, p);
- bump_cpu_timer(timer, now);
- if (unlikely(p->exit_state))
- return;
-
- /* Protect timer list r/w in arm_timer() */
- sighand = lock_task_sighand(p, &flags);
- if (!sighand)
- return;
} else {
- /*
- * Protect arm_timer() and timer sampling in case of call to
- * thread_group_cputime().
- */
- sighand = lock_task_sighand(p, &flags);
- if (unlikely(sighand == NULL)) {
- /*
- * The process has been reaped.
- * We can't even collect a sample any more.
- */
- cpu_timer_setexpires(ctmr, 0);
- return;
- } else if (unlikely(p->exit_state) && thread_group_empty(p)) {
- /* If the process is dying, no need to rearm */
- goto unlock;
- }
now = cpu_clock_sample_group(clkid, p, true);
- bump_cpu_timer(timer, now);
- /* Leave the sighand locked for the call below. */
}
+ bump_cpu_timer(timer, now);
+
+ /* Protect timer list r/w in arm_timer() */
+ sighand = lock_task_sighand(p, &flags);
+ if (unlikely(sighand == NULL))
+ return;
/*
* Now re-arm for the new expiry time.
*/
arm_timer(timer);
-unlock:
unlock_task_sighand(p, &flags);
}
--
2.25.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [tip: timers/core] posix-cpu-timers: Remove unnecessary locking around cpu_clock_sample_group
2020-02-28 17:09 ` [PATCH 2/5] posix-cpu-timers: Remove unnecessary locking around cpu_clock_sample_group Eric W. Biederman
@ 2020-03-01 10:27 ` tip-bot2 for Eric W. Biederman
0 siblings, 0 replies; 13+ messages in thread
From: tip-bot2 for Eric W. Biederman @ 2020-03-01 10:27 UTC (permalink / raw)
To: linux-tip-commits; +Cc: Eric W. Biederman, Thomas Gleixner, x86, LKML
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 60f2ceaa8111d9ec51af87bde4a6809f2b3235e4
Gitweb: https://git.kernel.org/tip/60f2ceaa8111d9ec51af87bde4a6809f2b3235e4
Author: Eric W. Biederman <ebiederm@xmission.com>
AuthorDate: Fri, 28 Feb 2020 11:09:19 -06:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 01 Mar 2020 11:21:44 +01:00
posix-cpu-timers: Remove unnecessary locking around cpu_clock_sample_group
As of e78c3496790e ("time, signal: Protect resource use statistics
with seqlock") cpu_clock_sample_group no longers needs siglock
protection. Unfortunately no one realized it at the time.
Remove the extra locking that is for cpu_clock_sample_group and not
for cpu_clock_sample. This significantly simplifies the code.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/878skmvdts.fsf@x220.int.ebiederm.org
---
kernel/time/posix-cpu-timers.c | 66 ++++++---------------------------
1 file changed, 12 insertions(+), 54 deletions(-)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 46cc188..40c2d83 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -718,31 +718,10 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
/*
* Sample the clock to take the difference with the expiry time.
*/
- if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+ if (CPUCLOCK_PERTHREAD(timer->it_clock))
now = cpu_clock_sample(clkid, p);
- } else {
- struct sighand_struct *sighand;
- unsigned long flags;
-
- /*
- * Protect against sighand release/switch in exit/exec and
- * also make timer sampling safe if it ends up calling
- * thread_group_cputime().
- */
- sighand = lock_task_sighand(p, &flags);
- if (unlikely(sighand == NULL)) {
- /*
- * The process has been reaped.
- * We can't even collect a sample any more.
- * Disarm the timer, nothing else to do.
- */
- cpu_timer_setexpires(ctmr, 0);
- return;
- } else {
- now = cpu_clock_sample_group(clkid, p, false);
- unlock_task_sighand(p, &flags);
- }
- }
+ else
+ now = cpu_clock_sample_group(clkid, p, false);
if (now < expires) {
itp->it_value = ns_to_timespec64(expires - now);
@@ -986,43 +965,22 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
/*
* Fetch the current sample and update the timer's expiry time.
*/
- if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+ if (CPUCLOCK_PERTHREAD(timer->it_clock))
now = cpu_clock_sample(clkid, p);
- bump_cpu_timer(timer, now);
- if (unlikely(p->exit_state))
- return;
-
- /* Protect timer list r/w in arm_timer() */
- sighand = lock_task_sighand(p, &flags);
- if (!sighand)
- return;
- } else {
- /*
- * Protect arm_timer() and timer sampling in case of call to
- * thread_group_cputime().
- */
- sighand = lock_task_sighand(p, &flags);
- if (unlikely(sighand == NULL)) {
- /*
- * The process has been reaped.
- * We can't even collect a sample any more.
- */
- cpu_timer_setexpires(ctmr, 0);
- return;
- } else if (unlikely(p->exit_state) && thread_group_empty(p)) {
- /* If the process is dying, no need to rearm */
- goto unlock;
- }
+ else
now = cpu_clock_sample_group(clkid, p, true);
- bump_cpu_timer(timer, now);
- /* Leave the sighand locked for the call below. */
- }
+
+ bump_cpu_timer(timer, now);
+
+ /* Protect timer list r/w in arm_timer() */
+ sighand = lock_task_sighand(p, &flags);
+ if (unlikely(sighand == NULL))
+ return;
/*
* Now re-arm for the new expiry time.
*/
arm_timer(timer);
-unlock:
unlock_task_sighand(p, &flags);
}
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/5] posix-cpu-timers: Pass the task into arm_timer
2020-02-28 17:07 [PATCH 0/5] posix-cpu-timers: Graceful handling of reaped processes Eric W. Biederman
2020-02-28 17:08 ` [PATCH 1/5] posix-cpu-timers: cpu_clock_sample_group no longer needs siglock Eric W. Biederman
2020-02-28 17:09 ` [PATCH 2/5] posix-cpu-timers: Remove unnecessary locking around cpu_clock_sample_group Eric W. Biederman
@ 2020-02-28 17:09 ` Eric W. Biederman
2020-03-01 10:27 ` [tip: timers/core] posix-cpu-timers: Pass the task into arm_timer() tip-bot2 for Eric W. Biederman
2020-02-28 17:11 ` [PATCH 4/5] posix-cpu-timers: Store a reference to a pid not a task Eric W. Biederman
2020-02-28 17:15 ` [PATCH 5/5] posix-cpu-timers: Stop disabling timers on mt-exec Eric W. Biederman
4 siblings, 1 reply; 13+ messages in thread
From: Eric W. Biederman @ 2020-02-28 17:09 UTC (permalink / raw)
To: linux-kernel; +Cc: Oleg Nesterov, Thomas Gleixner
We have already had to compute the task to take siglock before
calling arm_timer. So pass the benefit of that labor into arm_timer.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
kernel/time/posix-cpu-timers.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 3b27710f9505..dbbfa88881a3 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -482,12 +482,11 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
* Insert the timer on the appropriate list before any timers that
* expire later. This must be called with the sighand lock held.
*/
-static void arm_timer(struct k_itimer *timer)
+static void arm_timer(struct k_itimer *timer, struct task_struct *p)
{
int clkidx = CPUCLOCK_WHICH(timer->it_clock);
struct cpu_timer *ctmr = &timer->it.cpu;
u64 newexp = cpu_timer_getexpires(ctmr);
- struct task_struct *p = ctmr->task;
struct posix_cputimer_base *base;
if (CPUCLOCK_PERTHREAD(timer->it_clock))
@@ -660,7 +659,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
*/
cpu_timer_setexpires(ctmr, new_expires);
if (new_expires != 0 && val < new_expires) {
- arm_timer(timer);
+ arm_timer(timer, p);
}
unlock_task_sighand(p, &flags);
@@ -981,7 +980,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
/*
* Now re-arm for the new expiry time.
*/
- arm_timer(timer);
+ arm_timer(timer, p);
unlock_task_sighand(p, &flags);
}
--
2.25.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [tip: timers/core] posix-cpu-timers: Pass the task into arm_timer()
2020-02-28 17:09 ` [PATCH 3/5] posix-cpu-timers: Pass the task into arm_timer Eric W. Biederman
@ 2020-03-01 10:27 ` tip-bot2 for Eric W. Biederman
0 siblings, 0 replies; 13+ messages in thread
From: tip-bot2 for Eric W. Biederman @ 2020-03-01 10:27 UTC (permalink / raw)
To: linux-tip-commits; +Cc: Eric W. Biederman, Thomas Gleixner, x86, LKML
The following commit has been merged into the timers/core branch of tip:
Commit-ID: beb41d9cbe4179058634e05d60235b6155c7b6c6
Gitweb: https://git.kernel.org/tip/beb41d9cbe4179058634e05d60235b6155c7b6c6
Author: Eric W. Biederman <ebiederm@xmission.com>
AuthorDate: Fri, 28 Feb 2020 11:09:46 -06:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 01 Mar 2020 11:21:44 +01:00
posix-cpu-timers: Pass the task into arm_timer()
The task has been already computed to take siglock before calling
arm_timer. So pass the benefit of that labor into arm_timer().
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/8736auvdt1.fsf@x220.int.ebiederm.org
---
kernel/time/posix-cpu-timers.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 40c2d83..ef936c5 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -482,12 +482,11 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
* Insert the timer on the appropriate list before any timers that
* expire later. This must be called with the sighand lock held.
*/
-static void arm_timer(struct k_itimer *timer)
+static void arm_timer(struct k_itimer *timer, struct task_struct *p)
{
int clkidx = CPUCLOCK_WHICH(timer->it_clock);
struct cpu_timer *ctmr = &timer->it.cpu;
u64 newexp = cpu_timer_getexpires(ctmr);
- struct task_struct *p = ctmr->task;
struct posix_cputimer_base *base;
if (CPUCLOCK_PERTHREAD(timer->it_clock))
@@ -660,7 +659,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
*/
cpu_timer_setexpires(ctmr, new_expires);
if (new_expires != 0 && val < new_expires) {
- arm_timer(timer);
+ arm_timer(timer, p);
}
unlock_task_sighand(p, &flags);
@@ -980,7 +979,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
/*
* Now re-arm for the new expiry time.
*/
- arm_timer(timer);
+ arm_timer(timer, p);
unlock_task_sighand(p, &flags);
}
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/5] posix-cpu-timers: Store a reference to a pid not a task
2020-02-28 17:07 [PATCH 0/5] posix-cpu-timers: Graceful handling of reaped processes Eric W. Biederman
` (2 preceding siblings ...)
2020-02-28 17:09 ` [PATCH 3/5] posix-cpu-timers: Pass the task into arm_timer Eric W. Biederman
@ 2020-02-28 17:11 ` Eric W. Biederman
2020-03-01 10:27 ` [tip: timers/core] " tip-bot2 for Eric W. Biederman
2020-03-04 8:57 ` tip-bot2 for Eric W. Biederman
2020-02-28 17:15 ` [PATCH 5/5] posix-cpu-timers: Stop disabling timers on mt-exec Eric W. Biederman
4 siblings, 2 replies; 13+ messages in thread
From: Eric W. Biederman @ 2020-02-28 17:11 UTC (permalink / raw)
To: linux-kernel; +Cc: Oleg Nesterov, Thomas Gleixner
The posix cpu timers do not handle the death of a process well.
This is most clearly seen when a multi-threaded process calls exec
from a thread that is not a leader of the thread group. The posix cpu
timer code continues to pin the old thread group leader and is unable
to find the siglock from there.
This results in posix_cpu_timer_del being unable to delete a timer,
posix_cpu_timer_set being unable to set a timer. Further to
compensate for the problems in posix_cpu_timer_del on a multi-threaded
exec all timers that point at the multi-threaded task are stopped.
The code for the timers fundamentally needs to check if the target
process/thread is alive. This needs an extra level of indirection.
We already have that level indirection in struct pid.
So replace cpu.task with cpu.pid to get the needed extra layer
of indirection.
In addition to handling things more cleanly this reduces the amount of
memory a timer can pin when a process exits and then is reaped from
a task_struct to the vastly smaller struct pid.
Fixes: e0a70217107e ("posix-cpu-timers: workaround to suppress the problems with mt exec")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
include/linux/posix-timers.h | 2 +-
kernel/time/posix-cpu-timers.c | 73 +++++++++++++++++++++++++---------
2 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 3d10c84a97a9..e3f0f8585da4 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -69,7 +69,7 @@ static inline int clockid_to_fd(const clockid_t clk)
struct cpu_timer {
struct timerqueue_node node;
struct timerqueue_head *head;
- struct task_struct *task;
+ struct pid *pid;
struct list_head elist;
int firing;
};
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index dbbfa88881a3..1c21f2fd3d9b 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -118,6 +118,19 @@ static inline int validate_clock_permissions(const clockid_t clock)
return __get_task_for_clock(clock, false, false) ? 0 : -EINVAL;
}
+static inline enum pid_type cpu_timer_pid_type(struct k_itimer *timer)
+{
+ enum pid_type type = PIDTYPE_TGID;
+ if (CPUCLOCK_PERTHREAD(timer->it_clock))
+ type = PIDTYPE_PID;
+ return type;
+}
+
+static inline struct task_struct *cpu_timer_task_rcu(struct k_itimer *timer)
+{
+ return pid_task(timer->it.cpu.pid, cpu_timer_pid_type(timer));
+}
+
/*
* Update expiry time from increment, and increase overrun count,
* given the current clock sample.
@@ -391,7 +404,7 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
new_timer->kclock = &clock_posix_cpu;
timerqueue_init(&new_timer->it.cpu.node);
- new_timer->it.cpu.task = p;
+ new_timer->it.cpu.pid = get_task_pid(p, cpu_timer_pid_type(new_timer));
return 0;
}
@@ -404,13 +417,15 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
static int posix_cpu_timer_del(struct k_itimer *timer)
{
struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
+ struct task_struct *p;
struct sighand_struct *sighand;
unsigned long flags;
int ret = 0;
- if (WARN_ON_ONCE(!p))
- return -EINVAL;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Protect against sighand release/switch in exit/exec and process/
@@ -432,8 +447,10 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
unlock_task_sighand(p, &flags);
}
+out:
+ rcu_read_unlock();
if (!ret)
- put_task_struct(p);
+ put_pid(ctmr->pid);
return ret;
}
@@ -561,13 +578,21 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
u64 old_expires, new_expires, old_incr, val;
struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
+ struct task_struct *p;
struct sighand_struct *sighand;
unsigned long flags;
int ret = 0;
- if (WARN_ON_ONCE(!p))
- return -EINVAL;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p) {
+ /*
+ * If p has just been reaped, we can no
+ * longer get any information about it at all.
+ */
+ rcu_read_unlock();
+ return -ESRCH;
+ }
/*
* Use the to_ktime conversion because that clamps the maximum
@@ -584,8 +609,10 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
* If p has just been reaped, we can no
* longer get any information about it at all.
*/
- if (unlikely(sighand == NULL))
+ if (unlikely(sighand == NULL)) {
+ rcu_read_unlock();
return -ESRCH;
+ }
/*
* Disarm any old timer after extracting its expiry time.
@@ -690,6 +717,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
ret = 0;
out:
+ rcu_read_unlock();
if (old)
old->it_interval = ns_to_timespec64(old_incr);
@@ -701,10 +729,12 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
struct cpu_timer *ctmr = &timer->it.cpu;
u64 now, expires = cpu_timer_getexpires(ctmr);
- struct task_struct *p = ctmr->task;
+ struct task_struct *p;
- if (WARN_ON_ONCE(!p))
- return;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Easy part: convert the reload time.
@@ -712,7 +742,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
itp->it_interval = ktime_to_timespec64(timer->it_interval);
if (!expires)
- return;
+ goto out;
/*
* Sample the clock to take the difference with the expiry time.
@@ -733,6 +763,9 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
itp->it_value.tv_nsec = 1;
itp->it_value.tv_sec = 0;
}
+out:
+ rcu_read_unlock();
+ return;
}
#define MAX_COLLECTED 20
@@ -953,14 +986,15 @@ static void check_process_timers(struct task_struct *tsk,
static void posix_cpu_timer_rearm(struct k_itimer *timer)
{
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
- struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
+ struct task_struct *p;
struct sighand_struct *sighand;
unsigned long flags;
u64 now;
- if (WARN_ON_ONCE(!p))
- return;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Fetch the current sample and update the timer's expiry time.
@@ -975,13 +1009,16 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
/* Protect timer list r/w in arm_timer() */
sighand = lock_task_sighand(p, &flags);
if (unlikely(sighand == NULL))
- return;
+ goto out;
/*
* Now re-arm for the new expiry time.
*/
arm_timer(timer, p);
unlock_task_sighand(p, &flags);
+out:
+ rcu_read_unlock();
+ return;
}
/**
--
2.25.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [tip: timers/core] posix-cpu-timers: Store a reference to a pid not a task
2020-02-28 17:11 ` [PATCH 4/5] posix-cpu-timers: Store a reference to a pid not a task Eric W. Biederman
@ 2020-03-01 10:27 ` tip-bot2 for Eric W. Biederman
2020-03-04 8:57 ` tip-bot2 for Eric W. Biederman
1 sibling, 0 replies; 13+ messages in thread
From: tip-bot2 for Eric W. Biederman @ 2020-03-01 10:27 UTC (permalink / raw)
To: linux-tip-commits; +Cc: Eric W. Biederman, Thomas Gleixner, x86, LKML
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 672ebe8eb017a58ceeaca71ba9345b0612bf14d5
Gitweb: https://git.kernel.org/tip/672ebe8eb017a58ceeaca71ba9345b0612bf14d5
Author: Eric W. Biederman <ebiederm@xmission.com>
AuthorDate: Fri, 28 Feb 2020 11:11:06 -06:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 01 Mar 2020 11:21:44 +01:00
posix-cpu-timers: Store a reference to a pid not a task
posix cpu timers do not handle the death of a process well.
This is most clearly seen when a multi-threaded process calls exec from a
thread that is not the leader of the thread group. The posix cpu timer code
continues to pin the old thread group leader and is unable to find the
siglock from there.
This results in posix_cpu_timer_del being unable to delete a timer,
posix_cpu_timer_set being unable to set a timer. Further to compensate for
the problems in posix_cpu_timer_del on a multi-threaded exec all timers
that point at the multi-threaded task are stopped.
The code for the timers fundamentally needs to check if the target
process/thread is alive. This needs an extra level of indirection. This
level of indirection is already available in struct pid.
So replace cpu.task with cpu.pid to get the needed extra layer of
indirection.
In addition to handling things more cleanly this reduces the amount of
memory a timer can pin when a process exits and then is reaped from
a task_struct to the vastly smaller struct pid.
Fixes: e0a70217107e ("posix-cpu-timers: workaround to suppress the problems with mt exec")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/87wo86tz6d.fsf@x220.int.ebiederm.org
---
include/linux/posix-timers.h | 2 +-
kernel/time/posix-cpu-timers.c | 68 ++++++++++++++++++++++++---------
2 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 3d10c84..e3f0f85 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -69,7 +69,7 @@ static inline int clockid_to_fd(const clockid_t clk)
struct cpu_timer {
struct timerqueue_node node;
struct timerqueue_head *head;
- struct task_struct *task;
+ struct pid *pid;
struct list_head elist;
int firing;
};
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index ef936c5..afd1e95 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -118,6 +118,16 @@ static inline int validate_clock_permissions(const clockid_t clock)
return __get_task_for_clock(clock, false, false) ? 0 : -EINVAL;
}
+static inline enum pid_type cpu_timer_pid_type(struct k_itimer *timer)
+{
+ return CPUCLOCK_PERTHREAD(timer->it_clock) ? PIDTYPE_PID : PIDTYPE_TGID;
+}
+
+static inline struct task_struct *cpu_timer_task_rcu(struct k_itimer *timer)
+{
+ return pid_task(timer->it.cpu.pid, cpu_timer_pid_type(timer));
+}
+
/*
* Update expiry time from increment, and increase overrun count,
* given the current clock sample.
@@ -391,7 +401,7 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
new_timer->kclock = &clock_posix_cpu;
timerqueue_init(&new_timer->it.cpu.node);
- new_timer->it.cpu.task = p;
+ new_timer->it.cpu.pid = get_task_pid(p, cpu_timer_pid_type(new_timer));
return 0;
}
@@ -404,13 +414,15 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
static int posix_cpu_timer_del(struct k_itimer *timer)
{
struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
struct sighand_struct *sighand;
+ struct task_struct *p;
unsigned long flags;
int ret = 0;
- if (WARN_ON_ONCE(!p))
- return -EINVAL;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Protect against sighand release/switch in exit/exec and process/
@@ -432,8 +444,10 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
unlock_task_sighand(p, &flags);
}
+out:
+ rcu_read_unlock();
if (!ret)
- put_task_struct(p);
+ put_pid(ctmr->pid);
return ret;
}
@@ -561,13 +575,21 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
u64 old_expires, new_expires, old_incr, val;
struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
struct sighand_struct *sighand;
+ struct task_struct *p;
unsigned long flags;
int ret = 0;
- if (WARN_ON_ONCE(!p))
- return -EINVAL;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p) {
+ /*
+ * If p has just been reaped, we can no
+ * longer get any information about it at all.
+ */
+ rcu_read_unlock();
+ return -ESRCH;
+ }
/*
* Use the to_ktime conversion because that clamps the maximum
@@ -584,8 +606,10 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
* If p has just been reaped, we can no
* longer get any information about it at all.
*/
- if (unlikely(sighand == NULL))
+ if (unlikely(sighand == NULL)) {
+ rcu_read_unlock();
return -ESRCH;
+ }
/*
* Disarm any old timer after extracting its expiry time.
@@ -690,6 +714,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
ret = 0;
out:
+ rcu_read_unlock();
if (old)
old->it_interval = ns_to_timespec64(old_incr);
@@ -701,10 +726,12 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
struct cpu_timer *ctmr = &timer->it.cpu;
u64 now, expires = cpu_timer_getexpires(ctmr);
- struct task_struct *p = ctmr->task;
+ struct task_struct *p;
- if (WARN_ON_ONCE(!p))
- return;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Easy part: convert the reload time.
@@ -712,7 +739,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
itp->it_interval = ktime_to_timespec64(timer->it_interval);
if (!expires)
- return;
+ goto out;
/*
* Sample the clock to take the difference with the expiry time.
@@ -732,6 +759,8 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
itp->it_value.tv_nsec = 1;
itp->it_value.tv_sec = 0;
}
+out:
+ rcu_read_unlock();
}
#define MAX_COLLECTED 20
@@ -952,14 +981,15 @@ static void check_process_timers(struct task_struct *tsk,
static void posix_cpu_timer_rearm(struct k_itimer *timer)
{
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
- struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
+ struct task_struct *p;
struct sighand_struct *sighand;
unsigned long flags;
u64 now;
- if (WARN_ON_ONCE(!p))
- return;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Fetch the current sample and update the timer's expiry time.
@@ -974,13 +1004,15 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
/* Protect timer list r/w in arm_timer() */
sighand = lock_task_sighand(p, &flags);
if (unlikely(sighand == NULL))
- return;
+ goto out;
/*
* Now re-arm for the new expiry time.
*/
arm_timer(timer, p);
unlock_task_sighand(p, &flags);
+out:
+ rcu_read_unlock();
}
/**
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [tip: timers/core] posix-cpu-timers: Store a reference to a pid not a task
2020-02-28 17:11 ` [PATCH 4/5] posix-cpu-timers: Store a reference to a pid not a task Eric W. Biederman
2020-03-01 10:27 ` [tip: timers/core] " tip-bot2 for Eric W. Biederman
@ 2020-03-04 8:57 ` tip-bot2 for Eric W. Biederman
1 sibling, 0 replies; 13+ messages in thread
From: tip-bot2 for Eric W. Biederman @ 2020-03-04 8:57 UTC (permalink / raw)
To: linux-tip-commits; +Cc: Eric W. Biederman, Thomas Gleixner, x86, LKML
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 55e8c8eb2c7b6bf30e99423ccfe7ca032f498f59
Gitweb: https://git.kernel.org/tip/55e8c8eb2c7b6bf30e99423ccfe7ca032f498f59
Author: Eric W. Biederman <ebiederm@xmission.com>
AuthorDate: Fri, 28 Feb 2020 11:11:06 -06:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 04 Mar 2020 09:54:55 +01:00
posix-cpu-timers: Store a reference to a pid not a task
posix cpu timers do not handle the death of a process well.
This is most clearly seen when a multi-threaded process calls exec from a
thread that is not the leader of the thread group. The posix cpu timer code
continues to pin the old thread group leader and is unable to find the
siglock from there.
This results in posix_cpu_timer_del being unable to delete a timer,
posix_cpu_timer_set being unable to set a timer. Further to compensate for
the problems in posix_cpu_timer_del on a multi-threaded exec all timers
that point at the multi-threaded task are stopped.
The code for the timers fundamentally needs to check if the target
process/thread is alive. This needs an extra level of indirection. This
level of indirection is already available in struct pid.
So replace cpu.task with cpu.pid to get the needed extra layer of
indirection.
In addition to handling things more cleanly this reduces the amount of
memory a timer can pin when a process exits and then is reaped from
a task_struct to the vastly smaller struct pid.
Fixes: e0a70217107e ("posix-cpu-timers: workaround to suppress the problems with mt exec")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/87wo86tz6d.fsf@x220.int.ebiederm.org
---
include/linux/posix-timers.h | 2 +-
kernel/time/posix-cpu-timers.c | 73 ++++++++++++++++++++++++---------
2 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 3d10c84..e3f0f85 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -69,7 +69,7 @@ static inline int clockid_to_fd(const clockid_t clk)
struct cpu_timer {
struct timerqueue_node node;
struct timerqueue_head *head;
- struct task_struct *task;
+ struct pid *pid;
struct list_head elist;
int firing;
};
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index ef936c5..6df468a 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -118,6 +118,16 @@ static inline int validate_clock_permissions(const clockid_t clock)
return __get_task_for_clock(clock, false, false) ? 0 : -EINVAL;
}
+static inline enum pid_type cpu_timer_pid_type(struct k_itimer *timer)
+{
+ return CPUCLOCK_PERTHREAD(timer->it_clock) ? PIDTYPE_PID : PIDTYPE_TGID;
+}
+
+static inline struct task_struct *cpu_timer_task_rcu(struct k_itimer *timer)
+{
+ return pid_task(timer->it.cpu.pid, cpu_timer_pid_type(timer));
+}
+
/*
* Update expiry time from increment, and increase overrun count,
* given the current clock sample.
@@ -391,7 +401,12 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
new_timer->kclock = &clock_posix_cpu;
timerqueue_init(&new_timer->it.cpu.node);
- new_timer->it.cpu.task = p;
+ new_timer->it.cpu.pid = get_task_pid(p, cpu_timer_pid_type(new_timer));
+ /*
+ * get_task_for_clock() took a reference on @p. Drop it as the timer
+ * holds a reference on the pid of @p.
+ */
+ put_task_struct(p);
return 0;
}
@@ -404,13 +419,15 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
static int posix_cpu_timer_del(struct k_itimer *timer)
{
struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
struct sighand_struct *sighand;
+ struct task_struct *p;
unsigned long flags;
int ret = 0;
- if (WARN_ON_ONCE(!p))
- return -EINVAL;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Protect against sighand release/switch in exit/exec and process/
@@ -432,8 +449,10 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
unlock_task_sighand(p, &flags);
}
+out:
+ rcu_read_unlock();
if (!ret)
- put_task_struct(p);
+ put_pid(ctmr->pid);
return ret;
}
@@ -561,13 +580,21 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
u64 old_expires, new_expires, old_incr, val;
struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
struct sighand_struct *sighand;
+ struct task_struct *p;
unsigned long flags;
int ret = 0;
- if (WARN_ON_ONCE(!p))
- return -EINVAL;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p) {
+ /*
+ * If p has just been reaped, we can no
+ * longer get any information about it at all.
+ */
+ rcu_read_unlock();
+ return -ESRCH;
+ }
/*
* Use the to_ktime conversion because that clamps the maximum
@@ -584,8 +611,10 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
* If p has just been reaped, we can no
* longer get any information about it at all.
*/
- if (unlikely(sighand == NULL))
+ if (unlikely(sighand == NULL)) {
+ rcu_read_unlock();
return -ESRCH;
+ }
/*
* Disarm any old timer after extracting its expiry time.
@@ -690,6 +719,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
ret = 0;
out:
+ rcu_read_unlock();
if (old)
old->it_interval = ns_to_timespec64(old_incr);
@@ -701,10 +731,12 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
struct cpu_timer *ctmr = &timer->it.cpu;
u64 now, expires = cpu_timer_getexpires(ctmr);
- struct task_struct *p = ctmr->task;
+ struct task_struct *p;
- if (WARN_ON_ONCE(!p))
- return;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Easy part: convert the reload time.
@@ -712,7 +744,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
itp->it_interval = ktime_to_timespec64(timer->it_interval);
if (!expires)
- return;
+ goto out;
/*
* Sample the clock to take the difference with the expiry time.
@@ -732,6 +764,8 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
itp->it_value.tv_nsec = 1;
itp->it_value.tv_sec = 0;
}
+out:
+ rcu_read_unlock();
}
#define MAX_COLLECTED 20
@@ -952,14 +986,15 @@ static void check_process_timers(struct task_struct *tsk,
static void posix_cpu_timer_rearm(struct k_itimer *timer)
{
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
- struct cpu_timer *ctmr = &timer->it.cpu;
- struct task_struct *p = ctmr->task;
+ struct task_struct *p;
struct sighand_struct *sighand;
unsigned long flags;
u64 now;
- if (WARN_ON_ONCE(!p))
- return;
+ rcu_read_lock();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+ goto out;
/*
* Fetch the current sample and update the timer's expiry time.
@@ -974,13 +1009,15 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
/* Protect timer list r/w in arm_timer() */
sighand = lock_task_sighand(p, &flags);
if (unlikely(sighand == NULL))
- return;
+ goto out;
/*
* Now re-arm for the new expiry time.
*/
arm_timer(timer, p);
unlock_task_sighand(p, &flags);
+out:
+ rcu_read_unlock();
}
/**
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/5] posix-cpu-timers: Stop disabling timers on mt-exec
2020-02-28 17:07 [PATCH 0/5] posix-cpu-timers: Graceful handling of reaped processes Eric W. Biederman
` (3 preceding siblings ...)
2020-02-28 17:11 ` [PATCH 4/5] posix-cpu-timers: Store a reference to a pid not a task Eric W. Biederman
@ 2020-02-28 17:15 ` Eric W. Biederman
2020-03-01 10:27 ` [tip: timers/core] " tip-bot2 for Eric W. Biederman
2020-03-04 8:57 ` tip-bot2 for Eric W. Biederman
4 siblings, 2 replies; 13+ messages in thread
From: Eric W. Biederman @ 2020-02-28 17:15 UTC (permalink / raw)
To: linux-kernel; +Cc: Oleg Nesterov, Thomas Gleixner
The reasons Oleg added the extra posix_cpu_timers_exit_group are not
entirely clear from his commit message. Today all that
posix_cpu_timers_exit_group does is stop timers that are tracking the
task from firing. Every other operation on those timers is still
allowed.
The practical implication of this is posix_cpu_timer_del which could
not get the siglock after the thread group leader has exited (because
sighand == NULL) would be able to run successfully because the timer
was already dequeued.
With that locking issue fixed there is no point in disabling all
of the timers. So remove Oleg's ``tempoary'' hack.
Fixes: e0a70217107e ("posix-cpu-timers: workaround to suppress the problems with mt exec")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
kernel/exit.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/kernel/exit.c b/kernel/exit.c
index 502b4995b688..c7f32101c2c8 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -103,17 +103,8 @@ static void __exit_signal(struct task_struct *tsk)
#ifdef CONFIG_POSIX_TIMERS
posix_cpu_timers_exit(tsk);
- if (group_dead) {
+ if (group_dead)
posix_cpu_timers_exit_group(tsk);
- } else {
- /*
- * This can only happen if the caller is de_thread().
- * FIXME: this is the temporary hack, we should teach
- * posix-cpu-timers to handle this case correctly.
- */
- if (unlikely(has_group_leader_pid(tsk)))
- posix_cpu_timers_exit_group(tsk);
- }
#endif
if (group_dead) {
--
2.25.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [tip: timers/core] posix-cpu-timers: Stop disabling timers on mt-exec
2020-02-28 17:15 ` [PATCH 5/5] posix-cpu-timers: Stop disabling timers on mt-exec Eric W. Biederman
@ 2020-03-01 10:27 ` tip-bot2 for Eric W. Biederman
2020-03-04 8:57 ` tip-bot2 for Eric W. Biederman
1 sibling, 0 replies; 13+ messages in thread
From: tip-bot2 for Eric W. Biederman @ 2020-03-01 10:27 UTC (permalink / raw)
To: linux-tip-commits; +Cc: Eric W. Biederman, Thomas Gleixner, x86, LKML
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 71aebe0e9c84d06413a95857315e94305df51251
Gitweb: https://git.kernel.org/tip/71aebe0e9c84d06413a95857315e94305df51251
Author: Eric W. Biederman <ebiederm@xmission.com>
AuthorDate: Fri, 28 Feb 2020 11:15:03 -06:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Sun, 01 Mar 2020 11:21:45 +01:00
posix-cpu-timers: Stop disabling timers on mt-exec
The reasons why the extra posix_cpu_timers_exit_group() invocation has been
added are not entirely clear from the commit message. Today all that
posix_cpu_timers_exit_group() does is stop timers that are tracking the
task from firing. Every other operation on those timers is still allowed.
The practical implication of this is posix_cpu_timer_del() which could
not get the siglock after the thread group leader has exited (because
sighand == NULL) would be able to run successfully because the timer
was already dequeued.
With that locking issue fixed there is no point in disabling all of the
timers. So remove this ``tempoary'' hack.
Fixes: e0a70217107e ("posix-cpu-timers: workaround to suppress the problems with mt exec")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/87o8tityzs.fsf@x220.int.ebiederm.org
---
kernel/exit.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/kernel/exit.c b/kernel/exit.c
index 2833ffb..df54631 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -103,17 +103,8 @@ static void __exit_signal(struct task_struct *tsk)
#ifdef CONFIG_POSIX_TIMERS
posix_cpu_timers_exit(tsk);
- if (group_dead) {
+ if (group_dead)
posix_cpu_timers_exit_group(tsk);
- } else {
- /*
- * This can only happen if the caller is de_thread().
- * FIXME: this is the temporary hack, we should teach
- * posix-cpu-timers to handle this case correctly.
- */
- if (unlikely(has_group_leader_pid(tsk)))
- posix_cpu_timers_exit_group(tsk);
- }
#endif
if (group_dead) {
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [tip: timers/core] posix-cpu-timers: Stop disabling timers on mt-exec
2020-02-28 17:15 ` [PATCH 5/5] posix-cpu-timers: Stop disabling timers on mt-exec Eric W. Biederman
2020-03-01 10:27 ` [tip: timers/core] " tip-bot2 for Eric W. Biederman
@ 2020-03-04 8:57 ` tip-bot2 for Eric W. Biederman
1 sibling, 0 replies; 13+ messages in thread
From: tip-bot2 for Eric W. Biederman @ 2020-03-04 8:57 UTC (permalink / raw)
To: linux-tip-commits; +Cc: Eric W. Biederman, Thomas Gleixner, x86, LKML
The following commit has been merged into the timers/core branch of tip:
Commit-ID: b95e31c07c5eb4f5c0769f12b38b0343d7961040
Gitweb: https://git.kernel.org/tip/b95e31c07c5eb4f5c0769f12b38b0343d7961040
Author: Eric W. Biederman <ebiederm@xmission.com>
AuthorDate: Fri, 28 Feb 2020 11:15:03 -06:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 04 Mar 2020 09:54:55 +01:00
posix-cpu-timers: Stop disabling timers on mt-exec
The reasons why the extra posix_cpu_timers_exit_group() invocation has been
added are not entirely clear from the commit message. Today all that
posix_cpu_timers_exit_group() does is stop timers that are tracking the
task from firing. Every other operation on those timers is still allowed.
The practical implication of this is posix_cpu_timer_del() which could
not get the siglock after the thread group leader has exited (because
sighand == NULL) would be able to run successfully because the timer
was already dequeued.
With that locking issue fixed there is no point in disabling all of the
timers. So remove this ``tempoary'' hack.
Fixes: e0a70217107e ("posix-cpu-timers: workaround to suppress the problems with mt exec")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/87o8tityzs.fsf@x220.int.ebiederm.org
---
kernel/exit.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/kernel/exit.c b/kernel/exit.c
index 2833ffb..df54631 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -103,17 +103,8 @@ static void __exit_signal(struct task_struct *tsk)
#ifdef CONFIG_POSIX_TIMERS
posix_cpu_timers_exit(tsk);
- if (group_dead) {
+ if (group_dead)
posix_cpu_timers_exit_group(tsk);
- } else {
- /*
- * This can only happen if the caller is de_thread().
- * FIXME: this is the temporary hack, we should teach
- * posix-cpu-timers to handle this case correctly.
- */
- if (unlikely(has_group_leader_pid(tsk)))
- posix_cpu_timers_exit_group(tsk);
- }
#endif
if (group_dead) {
^ permalink raw reply related [flat|nested] 13+ messages in thread