All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: wen.yang@linux.dev
Cc: linux-trace-kernel@vger.kernel.org
Subject: Re: [PATCH v7 11/14] rv: Add tlob hybrid automaton monitor
Date: Sun, 11 Oct 2026 19:58:07 +0000	[thread overview]
Message-ID: <sashiko-outbox-167433@kernel.org> (raw)
In-Reply-To: <96c7ee8abbe9b9b840ca6e112744b5c74f0e9b8f.1791745088.git.wen.yang@linux.dev>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] rv: TOCTOU race in ha_setup_invariants allows hrtimer Use-After-Free
- [High] rv: deadlock in tlob_binding_lock between process context and RCU softirq
- [High] rv: tlob: list corruption due to lockless da_destroy_storage() calls
- [Medium] rv: race between tlob_stop_task and timer callback causes INVALID_STATE error
--

commit 90ea80dda3503cc5ac796d8401bafbbd97a373b9
Author: Wen Yang <wen.yang@linux.dev>

rv: Add tlob hybrid automaton monitor

tlob (task latency over budget) is a per-task hybrid automaton RV
monitor that tracks wall-clock time across a user-delimited code
section and emits an error when the elapsed time exceeds a configurable
budget.

> diff --git a/kernel/trace/rv/monitors/tlob/tlob.c b/kernel/trace/rv/monitors/tlob/tlob.c
> --- /dev/null
> +++ b/kernel/trace/rv/monitors/tlob/tlob.c
[ ... ]
> +static inline void tlob_detach_from_binding(struct tlob_record *rec)
> +{
> +	guard(spinlock)(&tlob_binding_lock);
> +
> +	if (!rec->binding)
> +		return;
> +	rec->binding = NULL;
> +	list_del_init(&rec->started_node);
> +}
> +
> +/*
> + * Per-record teardown during monitor disable.  TLOB_RETIRED claims it, so an
> + * exit or unbind racing disable frees the record once.
> + */
> +static inline void tlob_extra_cleanup(struct da_monitor *da_mon)
> +{
> +	struct ha_monitor *ha_mon = to_ha_monitor(da_mon);
> +	struct tlob_record *rec = ha_get_target(ha_mon);
> +
> +	if (!rec)
> +		return;
> +
> +	if (atomic_xchg(&rec->state, TLOB_RETIRED) == TLOB_RETIRED)
> +		return;
> +
> +	tlob_detach_from_binding(rec);
> +	call_rcu(&rec->rcu, tlob_rec_return_cb);
> +}

[Severity: High]
Does this lock acquisition risk a deadlock between process context and RCU
softirq?

The tlob_binding_lock is acquired in process context functions like
tlob_start_task() using scoped_guard(spinlock, &tlob_binding_lock), which
does not disable softirqs.

During monitor teardown, the RV framework's da_destroy_storage() frees the
monitor record via call_rcu(). The RCU callback executes in RCU_SOFTIRQ
context and invokes tlob_extra_cleanup(), which calls
tlob_detach_from_binding() and acquires the same lock.

If a process holding the lock is interrupted by the RCU softirq on the same
CPU, the softirq will deadlock attempting to acquire it. Should
tlob_binding_lock be acquired using spin_lock_bh() in all process-context
paths?

[ ... ]
> +static inline void ha_setup_invariants(struct ha_monitor *ha_mon,
> +				       enum states curr_state,
> +				       enum events event,
> +				       enum states next_state,
> +				       u64 time_ns)
> +{
> +	struct tlob_record *rec = ha_get_target(ha_mon);
> +
> +	if (next_state == stopped_tlob)
> +		return;
> +
> +	if (next_state >= state_max_tlob) {
> +		ha_cancel_timer(ha_mon);
> +		return;
> +	}
> +
> +	if (event != start_tlob) {
> +		/* A sched event racing the window end must not re-arm. */
> +		if (atomic_read_acquire(&rec->state) != TLOB_OPEN)
> +			return;
> +		ha_start_timer_ns(ha_mon, clk_elapsed_tlob,
> +				  BUDGET_NS(ha_mon), time_ns);
> +		return;
> +	}
> +
> +	ha_reset_clk_ns(ha_mon, clk_elapsed_tlob, time_ns);
> +	ha_start_timer_ns(ha_mon, clk_elapsed_tlob, BUDGET_NS(ha_mon),
> +			  time_ns);
> +	/* Reopen only a closed record; a teardown claim keeps it closed. */
> +	atomic_cmpxchg_release(&rec->state, TLOB_CLOSED, TLOB_OPEN);
> +}

[Severity: Critical]
Can this sequence allow a use-after-free of the hrtimer?

There appears to be a race between the state check and arming the timer.
A teardown path can concurrently claim the record by setting its state to
TLOB_RETIRED, cancel the timer, and queue the record for freeing via
call_rcu().

If the teardown occurs between ha_setup_invariants() checking the state and
calling ha_start_timer_ns(), the timer will be freshly re-armed on a record
that has already been queued for destruction.

Even in the start_tlob path, ha_start_timer_ns() is called unconditionally
before atomic_cmpxchg_release(). If the cmpxchg fails because of a
concurrent teardown, the armed timer is never rolled back.

Once the RCU grace period elapses, the record is freed. The still-armed
timer remains on the hrtimer rbtree, leading to a use-after-free when it
expires.

[ ... ]
> +static void tlob_stop_task(struct task_struct *task,
> +			   struct tlob_uprobe_binding *binding)
> +{
> +	struct ha_monitor *ha_mon;
> +	struct tlob_record *rec;
> +
> +	scoped_guard(rcu) {
> +		ha_mon = ha_get_monitor(task->pid, NULL);
> +		if (!ha_mon)
> +			return;
> +
> +		rec = ha_get_target(ha_mon);
> +		if (WARN_ON_ONCE(!rec))
> +			return;
> +
> +		/* Only the opener may end it; NULL (task exit) skips. */
> +		if (binding && READ_ONCE(rec->binding) != binding)
> +			return;
> +
> +		/* Claim the window end; the timer may have taken it first. */
> +		if (atomic_cmpxchg_release(&rec->state, TLOB_OPEN,
> +					   TLOB_CLOSED) != TLOB_OPEN)
> +			return;
> +
> +		ha_cancel_timer_sync(ha_mon);
> +	}
> +
> +	/* The DA returns to stopped; the record stays closed. */
> +	da_handle_event(task->pid, NULL, stop_tlob);
> +}

[Severity: Medium]
Will this result in an invalid state error if tlob_stop_task() races with
the timer callback?

tlob_stop_task() claims the window closure and then calls
ha_cancel_timer_sync(). If the hrtimer just expired and its callback is
running concurrently on another CPU, ha_cancel_timer_sync() spin-waits for
it to complete.

The generic timer callback will unconditionally emit a budget violation error
and reset the automaton to stopped_tlob. After ha_cancel_timer_sync()
returns, tlob_stop_task() injects the stop_tlob event.

Since the automaton defines stop_tlob from the stopped_tlob state as
invalid, this causes the framework to incorrectly flag an invalid transition
despite tlob_stop_task() legitimately ending the window.

[ ... ]
> +static void tlob_destroy_claimed(struct tlob_record *rec)
> +{
> +	pid_t id = rec->id;
> +
> +	tlob_detach_from_binding(rec);
> +
> +	scoped_guard(rcu) {
> +		struct ha_monitor *ha_mon = ha_get_monitor(id, NULL);
> +
> +		if (!WARN_ON_ONCE(!ha_mon))
> +			da_monitor_reset(&ha_mon->da_mon);
> +	}
> +	da_destroy_storage(id);
> +
> +	/* Readers may still hold rec; the pool slot returns after a GP. */
> +	call_rcu(&rec->rcu, tlob_rec_return_cb);
> +}

[Severity: High]
Does this code corrupt the hash table list pointers?

da_monitor_ht is a global hash table without internal locking. The function
da_destroy_storage() uses hash_del_rcu(), which modifies hlist pointers and
requires the caller to hold a writer lock to serialize against concurrent
writers.

While tlob_start_task() acquires tlob_binding_lock to serialize additions,
tlob_destroy_claimed() and the error path of tlob_start_task() call
da_destroy_storage() without holding tlob_binding_lock or any other
bucket-level lock.

Concurrent task exits or unbind operations that map to the same hash bucket
could corrupt the hash table's linked list.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1791745088.git.wen.yang@linux.dev?part=11

  reply	other threads:[~2026-10-11 19:58 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-11 19:39 [PATCH v7 00/14] rv: Add task latency over budget RV monitor wen.yang
2026-10-11 19:39 ` [PATCH v7 01/14] rv: Force environment reset action on HA monitor start wen.yang
2026-10-11 19:39 ` [PATCH v7 02/14] rv: Fix ha_monitor timer and invariant underflow wen.yang
2026-10-11 19:39 ` [PATCH v7 03/14] rv: Add a KUnit test for the HA timer underflow wen.yang
2026-10-11 19:52   ` sashiko-bot
2026-10-12  7:47   ` kernel test robot
2026-10-12  9:27   ` kernel test robot
2026-10-12 11:18   ` kernel test robot
2026-10-11 19:39 ` [PATCH v7 04/14] rv: Disarm HA timers on the storage free path wen.yang
2026-10-11 19:51   ` sashiko-bot
2026-10-11 19:39 ` [PATCH v7 05/14] rv: Add a KUnit test for " wen.yang
2026-10-11 19:50   ` sashiko-bot
2026-10-11 19:39 ` [PATCH v7 06/14] rv: Make da_monitor_reset_hook and EVENT_NONE_LBL overridable wen.yang
2026-10-11 19:53   ` sashiko-bot
2026-10-11 19:39 ` [PATCH v7 07/14] rv: Introduce DA_MON_ALLOCATION_STRATEGY wen.yang
2026-10-11 19:57   ` sashiko-bot
2026-10-11 19:39 ` [PATCH v7 08/14] rv: Add per-object teardown hook da_extra_cleanup wen.yang
2026-10-11 19:54   ` sashiko-bot
2026-10-11 19:39 ` [PATCH v7 09/14] rv: Add generic uprobe infrastructure for RV monitors wen.yang
2026-10-11 19:49   ` sashiko-bot
2026-10-11 19:39 ` [PATCH v7 10/14] rv: Add tlob model DOT file wen.yang
2026-10-11 19:39 ` [PATCH v7 11/14] rv: Add tlob hybrid automaton monitor wen.yang
2026-10-11 19:58   ` sashiko-bot [this message]
2026-10-11 19:39 ` [PATCH v7 12/14] rv: Add KUnit tests for the tlob monitor wen.yang
2026-10-11 19:39 ` [PATCH v7 13/14] selftests/verification: Add tlob selftests wen.yang
2026-10-11 19:51   ` sashiko-bot
2026-10-11 19:39 ` [PATCH v7 14/14] selftests/ftrace: Walk up parent dirs to find test.d/functions wen.yang
2026-10-12 11:58 ` [PATCH v7 00/14] rv: Add task latency over budget RV monitor Gabriele Monaco

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-167433@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=wen.yang@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.