Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: mctp i2c: check length before marking flow active

Currently, mctp_i2c_get_tx_flow_state() is called before the packet length
sanity check. This function marks a new flow as active in the MCTP core.

If the sanity check fails, mctp_i2c_xmit() returns early without calling
mctp_i2c_lock_nest(). This results in a mismatched locking state: the
flow is active, but the I2C bus lock was never acquired for it.

When the flow is later released, mctp_i2c_release_flow() will see the
active state and queue an unlock marker. The TX thread will then
decrement midev->i2c_lock_count from 0, causing it to underflow to -1.

This underflow permanently breaks the driver's locking logic, allowing
future transmissions to occur without holding the I2C bus lock, leading
to bus collisions and potential hardware hangs.

Move the mctp_i2c_get_tx_flow_state() call to after the length sanity
check to ensure we only transition the flow state if we are actually
going to proceed with the transmission and locking.

Fixes: f5b8abf9fc3d ("mctp i2c: MCTP I2C binding driver")
Signed-off-by: William A. Kennington III <william@wkennington.com>
Acked-by: Jeremy Kerr <jk@codeconstruct.com.au>
Link: https://patch.msgid.link/20260423074741.201460-1-william@wkennington.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

William A. Kennington III and committed by
Paolo Abeni
4ca07b92 0bb05e6a

+5 -3
+2 -2
drivers/net/mctp/mctp-i2c.c
··· 496 496 u8 *pecp; 497 497 int rc; 498 498 499 - fs = mctp_i2c_get_tx_flow_state(midev, skb); 500 - 501 499 hdr = (void *)skb_mac_header(skb); 502 500 /* Sanity check that packet contents matches skb length, 503 501 * and can't exceed MCTP_I2C_BUFSZ ··· 506 508 hdr->byte_count + 3, skb->len); 507 509 return; 508 510 } 511 + 512 + fs = mctp_i2c_get_tx_flow_state(midev, skb); 509 513 510 514 if (skb_tailroom(skb) >= 1) { 511 515 /* Linear case with space, we can just append the PEC */
+3 -1
net/sched/cls_flower.c
··· 556 556 struct netlink_ext_ack *extack) 557 557 { 558 558 struct cls_fl_head *head = fl_head_dereference(tp); 559 + struct fl_flow_mask *mask; 559 560 560 561 *last = false; 561 562 ··· 573 572 list_del_rcu(&f->list); 574 573 spin_unlock(&tp->lock); 575 574 576 - *last = fl_mask_put(head, f->mask); 575 + mask = f->mask; 577 576 if (!tc_skip_hw(f->flags)) 578 577 fl_hw_destroy_filter(tp, f, rtnl_held, extack); 579 578 tcf_unbind_filter(tp, &f->res); 580 579 __fl_put(f); 580 + *last = fl_mask_put(head, mask); 581 581 582 582 return 0; 583 583 }