Commit a5dec9f8 authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Thomas Gleixner
Browse files

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: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarFrederic Weisbecker <frederic@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20210726125513.271824-2-frederic@kernel.org
parent 1dae37c7
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -714,6 +714,12 @@ static inline void unlock_task_sighand(struct task_struct *task,
	spin_unlock_irqrestore(&task->sighand->siglock, *flags);
	spin_unlock_irqrestore(&task->sighand->siglock, *flags);
}
}


#ifdef CONFIG_LOCKDEP
extern void lockdep_assert_task_sighand_held(struct task_struct *task);
#else
static inline void lockdep_assert_task_sighand_held(struct task_struct *task) { }
#endif

static inline unsigned long task_rlimit(const struct task_struct *task,
static inline unsigned long task_rlimit(const struct task_struct *task,
		unsigned int limit)
		unsigned int limit)
{
{
+15 −0
Original line number Original line Diff line number Diff line
@@ -1413,6 +1413,21 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
	return sighand;
	return sighand;
}
}


#ifdef CONFIG_LOCKDEP
void lockdep_assert_task_sighand_held(struct task_struct *task)
{
	struct sighand_struct *sighand;

	rcu_read_lock();
	sighand = rcu_dereference(task->sighand);
	if (sighand)
		lockdep_assert_held(&sighand->siglock);
	else
		WARN_ON_ONCE(1);
	rcu_read_unlock();
}
#endif

/*
/*
 * send signal info to all the members of a group
 * send signal info to all the members of a group
 */
 */
+2 −0
Original line number Original line Diff line number Diff line
@@ -291,6 +291,8 @@ static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
	struct posix_cputimers *pct = &tsk->signal->posix_cputimers;
	struct posix_cputimers *pct = &tsk->signal->posix_cputimers;


	lockdep_assert_task_sighand_held(tsk);

	/* Check if cputimer isn't running. This is accessed without locking. */
	/* Check if cputimer isn't running. This is accessed without locking. */
	if (!READ_ONCE(pct->timers_active)) {
	if (!READ_ONCE(pct->timers_active)) {
		struct task_cputime sum;
		struct task_cputime sum;