The ice_ptp_request_ts() function is used to request a timestamp index for
use with a packet. When reserving an index, it sets the start time and
saves a pointer to the skb into the appropriate index. The function marks
the in_use bit first before doing any of these steps. The IRQ handler which
clears the timestamps reads the in_use bits uses a lockless flow for
reading the in_use bits to determine which ones are in-use. This is
necessary as actually processing a complete timestamp must be able to sleep
so we cannot hold the timestamp tracker lock over the entire sequence.
Additionally, blocking the Tx hotpath with such a lock indefinitely would
be problematic.

However, the existing flow now has a very narrow window where the IRQ
handler could see a timestamp as in-use but read a stale value for its
"start" time.

Fix this by ordering the sequence to mark the in_use bit last, and add a
memory barrier to prevent re-ordering of the previous writes to setup the
index.

This was found and reported by Sashiko while reviewing an unrelated change.

Closes: 
https://sashiko.dev/#/patchset/20260821-jk-e825c-minimized-fixes-v1-0-9d0731eb4858%40intel.com?part=7
Fixes: ea9b847cda64 ("ice: enable transmit timestamps for E810 devices")
Signed-off-by: Jacob Keller <[email protected]>
---
 drivers/net/ethernet/intel/ice/ice_ptp.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c 
b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 142d39ee5cc5..68537705e839 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -2672,11 +2672,13 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct 
sk_buff *skb)
                 * a reference to the skb and the start time to allow 
discarding old
                 * requests.
                 */
-               set_bit(idx, tx->in_use);
-               clear_bit(idx, tx->stale);
                tx->tstamps[idx].start = jiffies;
                tx->tstamps[idx].skb = skb_get(skb);
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+               clear_bit(idx, tx->stale);
+               /* Ensure index is setup before marking it as used */
+               smp_mb__before_atomic();
+               set_bit(idx, tx->in_use);
                ice_trace(tx_tstamp_request, skb, idx);
        }
 

-- 
2.55.0.814.gc42f45431d0f

Reply via email to