Skip to content

Commit a5dec9f

Browse files
Frederic WeisbeckerKAGA-KOKO
authored andcommitted
posix-cpu-timers: Assert task sighand is locked while starting cputime counter
Starting the process wide cputime counter needs to be done in the same sighand locking sequence than actually arming the related timer otherwise this races against concurrent timers setting/expiring in the same threadgroup. Detecting that the cputime counter is started without holding the sighand lock is a first step toward debugging such situations. Suggested-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 1dae37c commit a5dec9f

File tree

3 files changed

+23
-0
lines changed

3 files changed

+23
-0
lines changed

include/linux/sched/signal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,12 @@ static inline void unlock_task_sighand(struct task_struct *task,
714714
spin_unlock_irqrestore(&task->sighand->siglock, *flags);
715715
}
716716

717+
#ifdef CONFIG_LOCKDEP
718+
extern void lockdep_assert_task_sighand_held(struct task_struct *task);
719+
#else
720+
static inline void lockdep_assert_task_sighand_held(struct task_struct *task) { }
721+
#endif
722+
717723
static inline unsigned long task_rlimit(const struct task_struct *task,
718724
unsigned int limit)
719725
{

kernel/signal.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,21 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
14131413
return sighand;
14141414
}
14151415

1416+
#ifdef CONFIG_LOCKDEP
1417+
void lockdep_assert_task_sighand_held(struct task_struct *task)
1418+
{
1419+
struct sighand_struct *sighand;
1420+
1421+
rcu_read_lock();
1422+
sighand = rcu_dereference(task->sighand);
1423+
if (sighand)
1424+
lockdep_assert_held(&sighand->siglock);
1425+
else
1426+
WARN_ON_ONCE(1);
1427+
rcu_read_unlock();
1428+
}
1429+
#endif
1430+
14161431
/*
14171432
* send signal info to all the members of a group
14181433
*/

kernel/time/posix-cpu-timers.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
291291
struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
292292
struct posix_cputimers *pct = &tsk->signal->posix_cputimers;
293293

294+
lockdep_assert_task_sighand_held(tsk);
295+
294296
/* Check if cputimer isn't running. This is accessed without locking. */
295297
if (!READ_ONCE(pct->timers_active)) {
296298
struct task_cputime sum;

0 commit comments

Comments
 (0)