Merge tag 'firewire-fixes-6.19-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394

Pull firewire fix from Takashi Sakamoto:
"Fix a race condition introduced in v6.18.

Andreas Persson discovered this issue while working with Focusrite
Saffire Pro 40 (TCD33070). The fw_card instance maintains a linked
list of pending transactions, which must be protected against
concurrent access.

However, a commit b5725cfa4120 ("firewire: core: use spin lock
specific to timer for split transaction") unintentionally allowed
concurrent accesses to this list.

Fix this by adjusting the relevant critical sections to properly
serialize access"

* tag 'firewire-fixes-6.19-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394:
firewire: core: fix race condition against transaction list

+10 -9
+10 -9
drivers/firewire/core-transaction.c
··· 173 } 174 } 175 176 - static void start_split_transaction_timeout(struct fw_transaction *t, 177 - struct fw_card *card) 178 { 179 - unsigned long delta; 180 - 181 if (list_empty(&t->link) || WARN_ON(t->is_split_transaction)) 182 return; 183 184 t->is_split_transaction = true; 185 186 - // NOTE: This can be without irqsave when we can guarantee that __fw_send_request() for 187 - // local destination never runs in any type of IRQ context. 188 - scoped_guard(spinlock_irqsave, &card->split_timeout.lock) 189 - delta = card->split_timeout.jiffies; 190 mod_timer(&t->split_timeout_timer, jiffies + delta); 191 } 192 ··· 201 break; 202 case ACK_PENDING: 203 { 204 // NOTE: This can be without irqsave when we can guarantee that __fw_send_request() for 205 // local destination never runs in any type of IRQ context. 206 scoped_guard(spinlock_irqsave, &card->split_timeout.lock) { 207 t->split_timeout_cycle = 208 compute_split_timeout_timestamp(card, packet->timestamp) & 0xffff; 209 } 210 - start_split_transaction_timeout(t, card); 211 break; 212 } 213 case ACK_BUSY_X:
··· 173 } 174 } 175 176 + // card->transactions.lock should be acquired in advance for the linked list. 177 + static void start_split_transaction_timeout(struct fw_transaction *t, unsigned int delta) 178 { 179 if (list_empty(&t->link) || WARN_ON(t->is_split_transaction)) 180 return; 181 182 t->is_split_transaction = true; 183 184 mod_timer(&t->split_timeout_timer, jiffies + delta); 185 } 186 ··· 207 break; 208 case ACK_PENDING: 209 { 210 + unsigned int delta; 211 + 212 // NOTE: This can be without irqsave when we can guarantee that __fw_send_request() for 213 // local destination never runs in any type of IRQ context. 214 scoped_guard(spinlock_irqsave, &card->split_timeout.lock) { 215 t->split_timeout_cycle = 216 compute_split_timeout_timestamp(card, packet->timestamp) & 0xffff; 217 + delta = card->split_timeout.jiffies; 218 } 219 + 220 + // NOTE: This can be without irqsave when we can guarantee that __fw_send_request() for 221 + // local destination never runs in any type of IRQ context. 222 + scoped_guard(spinlock_irqsave, &card->transactions.lock) 223 + start_split_transaction_timeout(t, delta); 224 break; 225 } 226 case ACK_BUSY_X: