Re: [PATCH v13 03/11] can: bcm: add locking when updating filter and timer values

Oliver Hartkopp <[email protected]>
Newsgroups org.kernel.vger.linux-can,dev.linux.lists.sashiko-reviews
Message-ID <[email protected]>

On 14.07.26 12:27, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] Dropping bcm_rx_update_lock in bcm_rx_handler creates a TOCTOU race that can erroneously process a received frame as a filter and restart timers for an RX_RTR_FRAME operation.
> --

Fixed in patch 4

> 
> --- Patch [3]: [PATCH v13 03/11] can: bcm: add locking when updating filter and timer values ---
> commit 72b0ae7b8598826552a4ceb6840f50d02ba50085
> Author: Oliver Hartkopp <[email protected]>
> 
> can: bcm: add locking when updating filter and timer values
>      
> This commit adds a new bcm_rx_update_lock to protect timer and filter
> updates from concurrent access in bcm_rx_setup() and various RX handlers.
> It also fixes a race by normalizing the RTR flag on the staged buffer
> before registering the frames.
> 
> Link: https://lore.kernel.org/linux-can/[email protected]/
> 
>> diff --git a/net/can/bcm.c b/net/can/bcm.c
>> index b612135b017d1..af4bb4182bc29 100644
>> --- a/net/can/bcm.c
>> +++ b/net/can/bcm.c
> 
> [ ... ]
> 
>> @@ -729,9 +751,18 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
>>   	/* update statistics */
>>   	op->frames_abs++;
>>   
>> -	if (op->flags & RX_RTR_FRAME) {
>> +	/* snapshot the flag under lock: op->flags/op->frames may be updated
>> +	 * concurrently by bcm_rx_setup().
>> +	 */
>> +	spin_lock_bh(&op->bcm_rx_update_lock);
>> +	rtr_frame = op->flags & RX_RTR_FRAME;
>> +	if (rtr_frame)
>> +		memcpy(&rtrframe, op->frames, op->cfsiz);
>> +	spin_unlock_bh(&op->bcm_rx_update_lock);
>> +
>> +	if (rtr_frame) {
>>   		/* send reply for RTR-request (placed in op->frames[0]) */
>> -		bcm_can_tx(op);
>> +		bcm_can_tx(op, &rtrframe);
>>   		return;
>>   	}
>>   
>> @@ -743,6 +774,8 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
>>   			traffic_flags |= RX_OWN;
>>   	}
>>   
>> +	spin_lock_bh(&op->bcm_rx_update_lock);
>> +
> 
> [Severity: Medium]
> Could this lock split cause a race condition if a concurrent bcm_rx_setup()
> updates the operation to an RX_RTR_FRAME?
> 
> If bcm_rx_handler() initially sees rtr_frame == false and drops the lock:
> 
> CPU1 (bcm_rx_handler)
>      spin_lock_bh(&op->bcm_rx_update_lock);
>      rtr_frame = op->flags & RX_RTR_FRAME; // false
>      spin_unlock_bh(&op->bcm_rx_update_lock);
> 
> CPU2 (bcm_rx_setup)
>      spin_lock_bh(&op->bcm_rx_update_lock);
>      op->flags |= RX_RTR_FRAME;
>      // updates op->frames but does not clear op->kt_ival1
>      spin_unlock_bh(&op->bcm_rx_update_lock);
> 
> CPU1 (bcm_rx_handler)
>      spin_lock_bh(&op->bcm_rx_update_lock);
>      // Proceeds down the non-RTR path with op->flags now having RX_RTR_FRAME set
>      ...
>      bcm_rx_starttimer(op);
> 
> When bcm_rx_handler() reacquires the lock and proceeds along the non-RTR path,
> it will incorrectly compare the received frame against the new RTR reply frame,
> potentially sending a spurious RX_CHANGED.
> 
> Furthermore, since op->kt_ival1 is not cleared when switching to RTR mode, could
> this erroneously start a timer for an RTR operation and result in a spurious
> RX_TIMEOUT?
> 
>>   	if (op->flags & RX_FILTER_ID) {
>>   		/* the easiest case */
>>   		bcm_rx_update_and_send(op, op->last_frames, rxframe,
>> @@ -778,6 +811,8 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
>>   
>>   rx_starttimer:
>>   	bcm_rx_starttimer(op);
>> +
>> +	spin_unlock_bh(&op->bcm_rx_update_lock);
>>   }
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.