6.6.145-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 240/1266 USB: misc: uss720: unregister parport on probe failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
commit b4ecbdc4f8830f5586c4a5cfc384c00f20f8f8b3 upstream.
uss720_probe() registers a parport before reading the 1284 register used to detect unsupported Belkin F5U002 adapters. If get_1284_register() fails, the error path drops the driver private data and the USB device reference, but leaves the parport device registered.
Leaving the port registered is more than a private allocation leak:parport_register_port() has already reserved a parport number and registered the parport bus device, while pp->private_data still points at the private data that the common error path is about to release.
Undo the pre-announce registration in the get_1284_register() failure branch before jumping to the common private-data cleanup path. Clear priv->pp first, matching the disconnect path and avoiding a stale pointer in the private data.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
--- drivers/usb/misc/uss720.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/usb/misc/uss720.c +4 -1
@@ -732,8 +732,11 @@ static int uss720_probe(struct usb_inter* here. */ ret =get_1284_register (pp,0 , ®,GFP_KERNEL );dev_dbg (&intf->dev,"reg: %7ph\n" , priv->reg); -if (ret <0 ) +if (ret <0 ) { + priv->pp =NULL ; +parport_del_port (pp); goto probe_abort; + } ret =usb_find_last_int_in_endpoint (interface, &epd);if (!ret) {
Greg Kroah-Hartman
maintainerPATCH 241/1266 usb: mtu3: unmap request DMA on queue failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit 0bddda5a11665c210339de76d27ebbd1a2e0b43c upstream.
mtu3_gadget_queue() maps the request before checking whether the QMU GPD ring can accept another transfer. the request is returned with -EAGAIN before it is linked on the endpoint request list if mtu3_prepare_transfer() fails.
Normal completion and dequeue paths unmap requests from mtu3_req_complete(), but this error path never reaches that helper, so the DMA mapping is left active. Unmap the request before returning from the failed queue path.
--- drivers/usb/mtu3/mtu3_gadget.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/mtu3/mtu3_gadget.c +1 -0
@@ -304,6 +304,7 @@ static int mtu3_gadget_queue(struct usb_if (mtu3_prepare_transfer (mep)) { ret = -EAGAIN ; +usb_gadget_unmap_request (&mtu->g, req, mep->is_in); goto error; }
Greg Kroah-Hartman
maintainerPATCH 242/1266 USB: serial: keyspan_pda: fix information leak
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 6bfc8d01ac4068eced509f8fc74d0cd205e4dcec upstream.
The write() callback is supposed to return the number of characters accepted or a negative errno. Since the addition of write fifo support the keyspan_pda implementation will however return the number characters submitted to the device if the write urb is not already in use. If this number is larger than the number of characters passed to write(), the line discipline continues writing data from beyond the tty write buffer.
Fix the information leak by making sure that keyspan_pda_write_start() returns zero on success as intended.
--- drivers/usb/serial/keyspan_pda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/serial/keyspan_pda.c +1 -1
@@ -518,7 +518,7 @@ static int keyspan_pda_write_start(strucif (count == room)schedule_work (&priv->unthrottle_work); -return count; +return 0 ; }static void keyspan_pda_write_bulk_callback (struct urb *urb)
Greg Kroah-Hartman
maintainerPATCH 243/1266 USB: serial: option: add Telit Cinterion FE990D50 compositions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabio Porcedda <[email protected]>
commit b33ab1dd80f5c1742f49eb6ec7b337c5ffcf3d32 upstream.
Add support for Telit Cinterion FE990D50 compositions:
0x990: RNDIS + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (AT) +
tty (diag) + ADPL + adb
T: Bus=01 Lev=01 Prnt=01 Port=06 Cnt=03 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=0990 Rev=06.06 S: Manufacturer=Telit Cinterion S: Product=FE990 S: SerialNumber=90b6a3ed C: #Ifs=10 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=ef(misc ) Sub=04 Prot=01 Driver=rndis_host E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 8 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 9 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
0x991: rmnet + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (AT) +
tty (diag) + ADPL + adb
T: Bus=01 Lev=01 Prnt=01 Port=06 Cnt=03 Dev#= 9 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=0991 Rev=06.06 S: Manufacturer=Telit Cinterion S: Product=FE990 S: SerialNumber=90b6a3ed C: #Ifs= 9 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=(none) E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 6 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 8 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
0x992: MBIM + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (AT) +
tty (diag) + ADPL + adb
T: Bus=01 Lev=01 Prnt=01 Port=06 Cnt=03 Dev#= 12 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=0992 Rev=06.06 S: Manufacturer=Telit Cinterion S: Product=FE990 S: SerialNumber=90b6a3ed C: #Ifs=10 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 8 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 9 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
0x993: ECM + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (AT) +
tty (diag) + ADPL + adb
T: Bus=01 Lev=01 Prnt=01 Port=06 Cnt=03 Dev#= 15 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=0993 Rev=06.06 S: Manufacturer=Telit Cinterion S: Product=FE990 S: SerialNumber=90b6a3ed C: #Ifs=10 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=06 Prot=00 Driver=cdc_ether E: Ad=82(I) Atr=03(Int.) MxPS= 16 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 8 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 9 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
--- drivers/usb/serial/option.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
drivers/usb/serial/option.c +16 -0
@@ -1326,6 +1326,22 @@ static const struct usb_device_id option { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x30), /* Telit FE990D50 (RNDIS) */ + .driver_info = NCTRL(6) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x30), /* Telit FE990D50 (rmnet) */ + .driver_info = NCTRL(5) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x30), /* Telit FE990D50 (MBIM) */ + .driver_info = NCTRL(6) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x30), /* Telit FE990D50 (ECM) */ + .driver_info = NCTRL(6) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x60) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1031, 0xff), /* Telit LE910C1-EUX */ .driver_info = NCTRL(0) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */
Greg Kroah-Hartman
maintainerPATCH 244/1266 USB: serial: digi_acceleport: fix broken rx after throttle
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 83a3dfc018943b05b6daf3a6f891833e1aabfa1f upstream.
If the port is closed while throttled, the read urb is never resubmitted and the port will not receive any further data until the device is reconnected (or the driver is rebound).
Clear the throttle flags and submit the urb if needed when opening the port.
--- drivers/usb/serial/digi_acceleport.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
drivers/usb/serial/digi_acceleport.c +16 -0
@@ -1073,6 +1073,7 @@ static int digi_open(struct tty_struct *unsigned char buf[32 ];struct digi_port *priv =usb_get_serial_port_data (port);struct ktermios not_termios; +int throttled;/* be sure the device is started up */ if (digi_startup_device (port->serial) !=0 )
@@ -1100,6 +1101,21 @@ static int digi_open(struct tty_struct * not_termios.c_iflag = ~tty->termios.c_iflag;digi_set_termios (tty, port, ¬_termios); } + +spin_lock_irq (&priv->dp_port_lock); + throttled = priv->dp_throttle_restart; + priv->dp_throttled =0 ; + priv->dp_throttle_restart =0 ; +spin_unlock_irq (&priv->dp_port_lock); + +if (throttled) { + ret =usb_submit_urb (port->read_urb,GFP_KERNEL ); +if (ret) { +dev_err (&port->dev,"failed to submit read urb: %d\n" , ret); +return ret; + } + } +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 245/1266 USB: serial: digi_acceleport: fix hard lockup on disconnect
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 5c1ea24b53bf3bfb859f0a05573997487975da23 upstream.
If submitting the OOB write urb fails persistently (e.g if the device is being disconnected) the driver would loop indefinitely with interrupts disabled.
Check for urb submission errors when sending OOB commands to avoid hanging if, for example, open(), set_termios() or close() races with a physical disconnect.
This is issue was flagged by Sashiko when reviewing an unrelated change to the driver.
--- drivers/usb/serial/digi_acceleport.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/usb/serial/digi_acceleport.c +7 -5
@@ -396,12 +396,14 @@ static int digi_write_oob_command(struct len &= ~3 ;memcpy (oob_port->write_urb->transfer_buffer, buf, len); oob_port->write_urb->transfer_buffer_length = len; + ret =usb_submit_urb (oob_port->write_urb,GFP_ATOMIC ); -if (ret ==0 ) { - oob_priv->dp_write_urb_in_use =1 ; - count -= len; - buf += len; - } +if (ret) +break ; + + oob_priv->dp_write_urb_in_use =1 ; + count -= len; + buf += len; }spin_unlock_irqrestore (&oob_priv->dp_port_lock, flags);if (ret)
Greg Kroah-Hartman
maintainerPATCH 246/1266 USB: serial: digi_acceleport: fix write buffer corruption
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 24ca1fea8f2753bf33e1d458ec1ae5d9b7796a65 upstream.
The digi_write_inb_command() is supposed to wait for the write urb to become available or return an error, but instead it updates the transfer buffer and tries to resubmit the urb on timeout.
To make things worse, for commands like break control where no timeout is used, the driver would corrupt the urb immediately due to a broken jiffies comparison (on 32-bit machines this takes five minutes of uptime to trigger due to INITIAL_JIFFIES).
Fix this by adding the missing return on timeout and waiting indefinitely when no timeout has been specified as intended.
This issue was (sort of) flagged by Sashiko when reviewing an unrelated change to the driver.
--- drivers/usb/serial/digi_acceleport.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
drivers/usb/serial/digi_acceleport.c +10 -5
@@ -433,20 +433,22 @@ static int digi_write_inb_command(structint len;struct digi_port *priv =usb_get_serial_port_data (port);unsigned char *data = port->write_urb->transfer_buffer; +unsigned long expire;unsigned long flags;dev_dbg (&port->dev,"digi_write_inb_command: TOP: port=%d, count=%d\n" , priv->dp_port_num, count);if (timeout) - timeout += jiffies; -else - timeout =ULONG_MAX ; + expire = jiffies + timeout;spin_lock_irqsave (&priv->dp_port_lock, flags);while (count >0 && ret ==0 ) { -while (priv->dp_write_urb_in_use && -time_before (jiffies, timeout)) { +while (priv->dp_write_urb_in_use) { +if (timeout &&time_after (jiffies, expire)) { + ret = -ETIMEDOUT ; +break ; + }cond_wait_interruptible_timeout_irqrestore ( &priv->write_wait,DIGI_RETRY_TIMEOUT , &priv->dp_port_lock, flags);
@@ -455,6 +457,9 @@ static int digi_write_inb_command(structspin_lock_irqsave (&priv->dp_port_lock, flags); } +if (ret) +break ; +/* len must be a multiple of 4 and small enough to */ /* guarantee the write will send buffered data first, */ /* so commands are in order with data and not split */
Greg Kroah-Hartman
maintainerPATCH 247/1266 USB: ulpi: fix memory leak on registration failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 8af6812795869a66e9b26044f455b13deecdb69c upstream.
The allocated device name is never freed on early ULPI device registration failures.
Fix this by initialising the device structure earlier and releasing the initial reference whenever registration fails.
--- drivers/usb/common/ulpi.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
drivers/usb/common/ulpi.c +10 -13
@@ -281,28 +281,24 @@ static int ulpi_register(struct device * ulpi->dev.parent = dev;/* needed early for ops */ ulpi->dev.bus = &ulpi_bus; ulpi->dev.type = &ulpi_dev_type; + +device_initialize (&ulpi->dev); +dev_set_name (&ulpi->dev,"%s.ulpi" ,dev_name (dev));ACPI_COMPANION_SET (&ulpi->dev,ACPI_COMPANION (dev)); ret =ulpi_of_register (ulpi); -if (ret) { -kfree (ulpi); +if (ret)return ret; - } ret =ulpi_read_id (ulpi); -if (ret) { -of_node_put (ulpi->dev.of_node); -kfree (ulpi); +if (ret)return ret; - } - ret =device_register (&ulpi->dev); -if (ret) { -put_device (&ulpi->dev); + ret =device_add (&ulpi->dev); +if (ret)return ret; - } root =debugfs_create_dir (dev_name (&ulpi->dev), ulpi_root);debugfs_create_file ("regs" ,0444 , root, ulpi, &ulpi_regs_fops);
@@ -334,9 +330,10 @@ struct ulpi *ulpi_register_interface(str ulpi->ops = ops; ret =ulpi_register (dev, ulpi); -if (ret) +if (ret) { +put_device (&ulpi->dev);return ERR_PTR (ret); - + }return ulpi; }
Greg Kroah-Hartman
maintainerPATCH 248/1266 USB: usb-storage: ene_ub6250: restore media-ready check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Rao <[email protected]>
commit 5fc3f333c001f1e308bbcdeecdec0d054d24338b upstream.
Commit 1892bf90677a ("USB: usb-storage: Fix use of bitfields for hardware data in ene_ub6250.c") converted the media status fields from bitfields to bit masks.
The original ene_transport() test called ene_init() only when neither media type was ready:
!(sd_ready || ms_ready)
The converted test became:
!sd_ready || ms_ready
This is not equivalent. Restore the original semantics by testing that both ready bits are clear before calling ene_init().
--- drivers/usb/storage/ene_ub6250.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/storage/ene_ub6250.c +2 -1
@@ -2306,7 +2306,8 @@ static int ene_transport(struct scsi_cmn/*US_DEBUG(usb_stor_show_command(us, srb)); */ scsi_set_resid (srb,0 ); -if (unlikely (!(info->SD_Status & SD_Ready) || (info->MS_Status & MS_Ready))) +if (unlikely (!(info->SD_Status & SD_Ready) && + !(info->MS_Status & MS_Ready))) result =ene_init (us);if (result ==USB_STOR_XFER_GOOD ) { result =USB_STOR_TRANSPORT_ERROR ;
Greg Kroah-Hartman
maintainerPATCH 249/1266 usbip: tools: support SuperSpeedPlus devices
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
commit 195e667c8719480c320cd48ac0fbf1cb81d6ffe0 upstream.
USB devices running at SuperSpeedPlus report "10000" or "20000" in their sysfs speed attribute. usbip currently maps only "5000" to USB_SPEED_SUPER, so a SuperSpeedPlus device is imported as USB_SPEED_UNKNOWN.
The attach request is then rejected by vhci_hcd:
vhci_hcd: Failed attach request for unsupported USB speed: UNKNOWN
Map the SuperSpeedPlus sysfs speed values to USB_SPEED_SUPER_PLUS, use the SuperSpeed VHCI hub for SuperSpeedPlus devices, and recognize the gadget current_speed string used by the kernel.
--- tools/usb/usbip/libsrc/usbip_common.c | 2 ++ tools/usb/usbip/libsrc/usbip_device_driver.c | 4 ++++ tools/usb/usbip/libsrc/vhci_driver.c | 1 + 3 files changed, 7 insertions(+)
tools/usb/usbip/libsrc/usbip_common.c +2 -0
@@ -29,6 +29,8 @@ static const struct speed_string speed_s { USB_SPEED_HIGH, "480", "High Speed(480Mbps)" }, { USB_SPEED_WIRELESS, "53.3-480", "Wireless"}, { USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" }, + { USB_SPEED_SUPER_PLUS, "10000", "Super Speed Plus(10000Mbps)" }, + { USB_SPEED_SUPER_PLUS, "20000", "Super Speed Plus(20000Mbps)" }, { 0, NULL, NULL } };
tools/usb/usbip/libsrc/usbip_device_driver.c +4 -0
@@ -57,6 +57,10 @@ static struct { .speed = USB_SPEED_SUPER, .name = "super-speed", }, + { + .speed = USB_SPEED_SUPER_PLUS, + .name = "super-speed-plus", + }, }; static
tools/usb/usbip/libsrc/vhci_driver.c +1 -0
@@ -338,6 +338,7 @@ int usbip_vhci_get_free_port(uint32_t spswitch (speed) {case USB_SPEED_SUPER : +case USB_SPEED_SUPER_PLUS :if (vhci_driver->idev[i].hub !=HUB_SPEED_SUPER )continue ;break ;
Greg Kroah-Hartman
maintainerPATCH 250/1266 usbip: vudc: fix NULL deref in vep_dequeue()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sam Day <[email protected]>
commit c5371e0b91b24159a3ebaa61e70b0980bcf03c0a upstream.
vep_alloc_request() wasn't initializing vrequest->udc, so cancellations on the FunctionFS AIO path were arriving in vep_dequeue without a valid UDC reference.
Since vrequest->udc is never actually properly used anywhere, we opt to remove it, and update vep_dequeue to obtain a reference to the udc with ep_to_vudc(), consistent with the other vep_ ops.
AFAICT this bug has existed for ~10 years. Seems that nobody has really stressed the FunctionFS AIO path on usbip's vudc.
I tested this fix in a QEMU aarch64 guest driving FunctionFS endpoints via AIO. Before the fix, running usbip attach from the host would cause the guest to oops with the following backtrace:
Call trace: vep_dequeue+0x1c/0xe4 (P) usb_ep_dequeue+0x14/0x20 ffs_aio_cancel+0x24/0x34 __arm64_sys_io_cancel+0xb0/0x124 do_el0_svc+0x68/0x100 el0_svc+0x18/0x5c el0t_64_sync_handler+0x98/0xdc el0t_64_sync+0x154/0x158
--- drivers/usb/usbip/vudc.h | 1 - drivers/usb/usbip/vudc_dev.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-)
drivers/usb/usbip/vudc.h +0 -1
@@ -38,7 +38,6 @@ struct vep {struct vrequest {struct usb_request req; -struct vudc *udc;struct list_head req_entry;/* Request queue */ };
drivers/usb/usbip/vudc_dev.c +1 -3
@@ -333,7 +333,6 @@ static int vep_queue(struct usb_ep *_ep,static int vep_dequeue (struct usb_ep *_ep,struct usb_request *_req) {struct vep *ep; -struct vrequest *req;struct vudc *udc;struct vrequest *lst;unsigned long flags;
@@ -343,8 +342,7 @@ static int vep_dequeue(struct usb_ep *_ereturn ret; ep =to_vep (_ep); - req =to_vrequest (_req); - udc = req->udc; + udc =ep_to_vudc (ep);if (!udc->driver)return -ESHUTDOWN ;
Greg Kroah-Hartman
maintainerPATCH 251/1266 usb: typec: anx7411: use devm_pm_runtime_enable()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
commit 0ef7cc27da8b9e315a4a5a665c68c44206f5e559 upstream.
anx7411_i2c_probe() enables runtime PM before returning successfully, but anx7411_i2c_remove() tears down the Type-C partner state, workqueue, dummy I2C device, mux, switch and port without disabling runtime PM.
Use devm_pm_runtime_enable() so runtime PM is disabled automatically on driver detach. Since devres action registration can fail, route that failure through the existing probe unwind path.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
--- drivers/usb/typec/anx7411.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/typec/anx7411.c +3 -1
@@ -1542,7 +1542,9 @@ static int anx7411_i2c_probe(struct i2c_if (anx7411_typec_check_connection (plat))dev_err (dev,"check status\n" ); -pm_runtime_enable (dev); + ret =devm_pm_runtime_enable (dev); +if (ret) + goto free_wq;return 0 ;
Greg Kroah-Hartman
maintainerPATCH 252/1266 usb: typec: class: drop PD lookup reference
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuangpeng Bai <[email protected]>
commit 43ae2f90b70cda374c487c1639a01d0f14e5d583 upstream.
usb_power_delivery_find() wraps class_find_device_by_name(). That helper returns a device reference that must be released by the caller.
select_usb_power_delivery_store() only needs this reference while calling the pd_set callback. Drop it once the callback returns. Otherwise the sysfs write can pin the selected USB Power Delivery object and prevent it from being released on unregister.
--- drivers/usb/typec/class.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/typec/class.c +1 -0
@@ -1277,6 +1277,7 @@ static ssize_t select_usb_power_deliveryreturn -EINVAL ; ret = port->ops->pd_set (port, pd); +put_device (&pd->dev);if (ret)return ret;
Greg Kroah-Hartman
maintainerPATCH 253/1266 usb: typec: tcpm: Validate SVID index in svdm_consume_modes()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Badhri Jagan Sridharan <[email protected]>
commit 7b681dd5fbf60b24a13c14661e5b7735759fb491 upstream.
In svdm_consume_modes(), the SVID value is read from pmdata->svids using pmdata->svid_index as an array index without bounds validation:
paltmode->svid = pmdata->svids[pmdata->svid_index];
If pmdata->svid_index is driven beyond SVID_DISCOVERY_MAX (16), it results in an out-of-bounds read of the pmdata->svids array. Because pd_mode_data is embedded inside struct tcpm_port, indexing past svids reads into adjacent fields. In particular:
- At index 16, it reads the altmodes count.
- At index 18 and beyond, it reads into altmode_desc[], which contains partner-supplied SVDM Discovery Modes VDOs.
By injecting a chosen SVID into altmode_desc[0].vdo and driving svid_index to 20, the partner can force paltmode->svid to be loaded with an arbitrary, partner- chosen SVID, which is then registered via typec_partner_register_altmode().
Fix this by validating that pmdata->svid_index is non-negative and strictly less than pmdata->nsvids before accessing the pmdata->svids array inside svdm_consume_modes().
--- drivers/usb/typec/tcpm/tcpm.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/typec/tcpm/tcpm.c +5 -0
@@ -1555,6 +1555,11 @@ static void svdm_consume_modes(struct tcreturn ; } +if (pmdata->svid_index <0 || pmdata->svid_index >= pmdata->nsvids) { +tcpm_log (port,"Invalid SVID index %d" , pmdata->svid_index); +return ; + } +for (i =1 ; i < cnt; i++) { paltmode = &pmdata->altmode_desc[pmdata->altmodes];memset (paltmode,0 ,sizeof (*paltmode));
Greg Kroah-Hartman
maintainerPATCH 254/1266 usb: typec: ucsi: Invert DisplayPort role assignment
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrei Kuchynski <[email protected]>
commit d092d7edf8faefa3e27b9fc7f0e7904b06c833a2 upstream.
The existing implementation assigned these flags backwards, configuring the partner's DisplayPort role to match the port's role instead of complementing it.
This prevents proper configuration during DP altmode activation, often causing pin_assignment to remain 0 in dp_altmode_configure() and resulting in VDM negotiation failures:
[ 583.328246] typec port1.1: VDM 0xff01a150 failed
Additionally, the fix ensures that the pin_assignment sysfs attribute displays the correct values.
--- drivers/usb/typec/ucsi/displayport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/typec/ucsi/displayport.c +2 -2
@@ -166,12 +166,12 @@ static int ucsi_displayport_status_updat* that Multi-function is preferred. */ if (DP_CAP_CAPABILITY (cap) &DP_CAP_UFP_D ) { - dp->data.status |=DP_STATUS_CON_UFP_D ; + dp->data.status |=DP_STATUS_CON_DFP_D ;if (DP_CAP_UFP_D_PIN_ASSIGN (cap) &BIT (DP_PIN_ASSIGN_D )) dp->data.status |=DP_STATUS_PREFER_MULTI_FUNC ; }else { - dp->data.status |=DP_STATUS_CON_DFP_D ; + dp->data.status |=DP_STATUS_CON_UFP_D ;if (DP_CAP_DFP_D_PIN_ASSIGN (cap) &BIT (DP_PIN_ASSIGN_D )) dp->data.status |=DP_STATUS_PREFER_MULTI_FUNC ;
Greg Kroah-Hartman
maintainerPATCH 255/1266 usb: typec: ucsi: Pass full DP config payload in SET_NEW_CAM for DP alt mode
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Madhu M <[email protected]>
commit 735a461d060d4eeb2f9732aba1295bc32a3982e2 upstream.
In the UCSI Specification Revision 3.1 RC1, bits 32-63 of the SET_NEW_CAM command hold the 32-bit Alternate Mode Specific (AMSpecific) field.
For DisplayPort Alternate Mode, this field must contain the full 32-bit DisplayPort configuration VDO payload that the OPM wants the connector to operate in, rather than just the pin assignment value. This AMSpecific value follows the DisplayPort Configurations defined in the DisplayPort Alt Mode on USB Type-C Specification v2.1a, Table 5-13: SOP DisplayPort Configurations.
--- drivers/usb/typec/ucsi/displayport.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/usb/typec/ucsi/displayport.c +1 -2
@@ -185,13 +185,12 @@ static int ucsi_displayport_status_updatstatic int ucsi_displayport_configure (struct ucsi_dp *dp) { -u32 pins =DP_CONF_GET_PIN_ASSIGN (dp->data.conf);u64 command;if (!dp->override)return 0 ; - command =UCSI_CMD_SET_NEW_CAM (dp->con->num,1 , dp->offset, pins); + command =UCSI_CMD_SET_NEW_CAM (dp->con->num,1 , dp->offset, dp->data.conf);return ucsi_send_command (dp->con->ucsi, command,NULL ,0 ); }
Greg Kroah-Hartman
maintainerPATCH 256/1266 usb: typec: ucsi: ccg: Fix use-after-free of ucsi on remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <[email protected]>
commit 1f0bdc2884b67de337215079bba166df0cdf4ac5 upstream.
The threaded IRQ handler ccg_irq_handler() calls ucsi_notify_common(), which on a connector-change event calls ucsi_connector_change() and schedules connector work. In ucsi_ccg_remove(), ucsi_destroy() frees uc->ucsi (kfree) before free_irq() is called, so a handler invocation already in flight may access the freed object after ucsi_destroy().
CPU 0 (remove) | CPU 1 (threaded IRQ)
ucsi_destroy(uc->ucsi) | ccg_irq_handler()
kfree(ucsi) // FREE | ucsi_notify_common(uc->ucsi) // USEMove free_irq() before ucsi_destroy() in the remove path. It is kept after ucsi_unregister(): ucsi_unregister() cancels connector work whose handler issues GET_CONNECTOR_STATUS through ucsi_send_command_common(), which waits for a completion that is signalled from the IRQ handler, so the IRQ must stay active until that work has been cancelled.
The probe error path already orders free_irq() before ucsi_destroy().
This bug was found by static analysis.
--- drivers/usb/typec/ucsi/ucsi_ccg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/typec/ucsi/ucsi_ccg.c +1 -1
@@ -1440,8 +1440,8 @@ static void ucsi_ccg_remove(struct i2c_ccancel_work_sync (&uc->work);pm_runtime_disable (uc->dev);ucsi_unregister (uc->ucsi); -ucsi_destroy (uc->ucsi);free_irq (uc->irq, uc); +ucsi_destroy (uc->ucsi); }static const struct of_device_id ucsi_ccg_of_match_table[] = {
Greg Kroah-Hartman
maintainerPATCH 257/1266 usb: typec: ucsi: cancel pending work on system suspend
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Menzel <[email protected]>
commit 7c4a234bd31a64a8dbd0140dc812da592c5e0787 upstream.
On a Dell XPS 13 9360 (BIOS 2.21.0), entering system suspend (deep/S3) races a pending UCSI connector-change worker against the ACPI EC teardown. The worker evaluates the UCSI _DSM (GET_CONNECTOR_STATUS), whose AML accesses the Embedded Controller. By that point the ACPI EC has already been stopped for suspend, so the EC address space handler rejects the access with AE_BAD_PARAMETER, aborting the AML and failing the connector query:
[22314.689495] ACPI: EC: interrupt blocked
[22314.711981] ACPI: PM: Preparing to enter system sleep state S3
[22314.743260] ACPI: EC: event blocked
[22314.743265] ACPI: EC: EC stopped
[22314.743267] ACPI: PM: Saving platform NVS memory
[22314.744241] ACPI Error: AE_BAD_PARAMETER, Returned by Handler for [EmbeddedControl] (20260408/evregion-303)
[22314.744432] ACPI Error: Aborting method \_SB.PCI0.LPCB.ECDV.ECW1 due to previous error (AE_BAD_PARAMETER) (20260408/psparse-543)
[22314.744673] ACPI Error: Aborting method \ECWB due to previous error (AE_BAD_PARAMETER) (20260408/psparse-543)
[22314.745201] ACPI Error: Aborting method \_SB.UBTC._DSM due to previous error (AE_BAD_PARAMETER) (20260408/psparse-543)
[22314.745394] ACPI: \_SB_.UBTC: failed to evaluate _DSM c298836f-a47c-e411-ad36-631042b5008f rev:1 func:1 (0x1001)
[22314.745414] ucsi_acpi USBC000:00: ucsi_acpi_dsm: failed to evaluate _DSM 1
[22314.745424] ucsi_acpi USBC000:00: ucsi_handle_connector_change: GET_CONNECTOR_STATUS failed (-5)ucsi_acpi implements a resume callback but no suspend callback, so nothing cancels the connector-change work before the firmware/EC is torn down.
Add a ucsi_suspend() core helper that cancels the pending init and connector-change work, and wire it into ucsi_acpi's PM ops. The connector state is re-read on resume by ucsi_resume(), so cancelling the work loses nothing.
--- drivers/usb/typec/ucsi/ucsi.c | 20 ++++++++++++++++++++ drivers/usb/typec/ucsi/ucsi.h | 1 + drivers/usb/typec/ucsi/ucsi_acpi.c | 10 +++++++++- 3 files changed, 30 insertions(+), 1 deletion(-)
drivers/usb/typec/ucsi/ucsi.c +20 -0
@@ -1533,6 +1533,26 @@ static void ucsi_resume_work(struct work } } +int ucsi_suspend (struct ucsi *ucsi) +{ +int i; + +/* +* Cancel pending work so it cannot access the firmware after the ACPI +* EC is stopped for suspend; state is re-read on resume. +*/ +cancel_delayed_work_sync (&ucsi->work); + +if (!ucsi->connector) +return 0 ; + +for (i =0 ; i < ucsi->cap.num_connectors; i++) +cancel_work_sync (&ucsi->connector[i].work); + +return 0 ; +} +EXPORT_SYMBOL_GPL (ucsi_suspend); +int ucsi_resume (struct ucsi *ucsi) {if (ucsi->connector)
drivers/usb/typec/ucsi/ucsi.h +1 -0
@@ -386,6 +386,7 @@ int ucsi_send_command(struct ucsi *ucsi, void *retval, size_t size);void ucsi_altmode_update_active (struct ucsi_connector *con); +int ucsi_suspend (struct ucsi *ucsi);int ucsi_resume (struct ucsi *ucsi);#if IS_ENABLED (CONFIG_POWER_SUPPLY )
drivers/usb/typec/ucsi/ucsi_acpi.c +9 -1
@@ -288,6 +288,13 @@ static void ucsi_acpi_remove(struct plat ucsi_acpi_notify); } +static int ucsi_acpi_suspend (struct device *dev) +{ +struct ucsi_acpi *ua =dev_get_drvdata (dev); + +return ucsi_suspend (ua->ucsi); +} +static int ucsi_acpi_resume (struct device *dev) {struct ucsi_acpi *ua =dev_get_drvdata (dev);
@@ -295,7 +302,8 @@ static int ucsi_acpi_resume(struct devicreturn ucsi_resume (ua->ucsi); } -static DEFINE_SIMPLE_DEV_PM_OPS(ucsi_acpi_pm_ops, NULL, ucsi_acpi_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(ucsi_acpi_pm_ops, ucsi_acpi_suspend, + ucsi_acpi_resume);static const struct acpi_device_id ucsi_acpi_match[] = { {"PNP0CA0" ,0 },
Greg Kroah-Hartman
maintainerPATCH 258/1266 iio: temperature: ltc2983: Fix n_wires default bypassing rotation check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liviu Stan <[email protected]>
[ Upstream commit 434c150752675f44dc52c384a7fa22e5176bc35a ]
When adi,number-of-wires is absent, n_wires is left at 0. The binding documents a default of 2 wires, matching the hardware default. However the current-rotate validation checks n_wires == 2 || n_wires == 3, so with n_wires = 0 the guard is bypassed and adi,current-rotate is accepted for a 2-wire RTD.
Initialize n_wires = 2 to match the binding default and ensure the rotation check fires correctly when the property is absent.
[ Liviu Stan: resolve conflict - keep fwnode_handle *ref declaration
which was removed upstream ]
--- drivers/iio/temperature/ltc2983.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/temperature/ltc2983.c +1 -1
@@ -751,7 +751,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,int ret =0 ;struct device *dev = &st->spi->dev;struct fwnode_handle *ref; -u32 excitation_current =0 , n_wires =0 ; +u32 excitation_current =0 , n_wires =2 ; rtd =devm_kzalloc (dev,sizeof (*rtd),GFP_KERNEL );if (!rtd)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 259/1266 PCI: Always lift 2.5GT/s restriction in PCIe failed link retraining
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
commit 72780f7964684939d7d2f69c348876213b184484 upstream.
Discard Vendor:Device ID matching in the PCIe failed link retraining quirk and ignore the link status for the removal of the 2.5GT/s speed clamp, whether applied by the quirk itself or the firmware earlier on. Revert to the original target link speed if this final link retraining has failed.
This is so that link training noise in hot-plug scenarios does not make a link remain clamped to the 2.5GT/s speed where an event race has led the quirk to apply the speed clamp for one device, only to leave it in place for a subsequent device to be plugged in.
Refer to the Link Capabilities register directly for the maximum link speed determination so as to streamline backporting.
--- drivers/pci/quirks.c | 51 +++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 31 deletions(-)
drivers/pci/quirks.c +20 -31
@@ -68,11 +68,10 @@* Restrict the speed to 2.5GT/s then with the Target Link Speed field, * request a retrain and check the result. * -* If this turns out successful and we know by the Vendor:Device ID it is -* safe to do so, then lift the restriction, letting the devices negotiate -* a higher speed. Also check for a similar 2.5GT/s speed restriction the -* firmware may have already arranged and lift it with ports that already -* report their data link being up. +* If this turns out successful, or where a 2.5GT/s speed restriction has +* been previously arranged by the firmware and the port reports its link +* already being up, lift the restriction, in a hope it is safe to do so, +* letting the devices negotiate a higher speed. * * Otherwise revert the speed to the original setting and request a retrain * again to remove any residual state, ignoring the result as it's supposed
@@ -83,12 +82,9 @@*/ int pcie_failed_link_retrain (struct pci_dev *dev) { -static const struct pci_device_id ids[] = { - {PCI_VDEVICE (ASMEDIA ,0x2824 ) },/* ASMedia ASM2824 */ - {} - }; -u16 lnksta, lnkctl2; +u16 lnksta, lnkctl2, oldlnkctl2;int ret = -ENOTTY ; +u32 lnkcap;if (!pci_is_pcie (dev) || !pcie_downstream_port (dev) || !pcie_cap_has_lnkctl2 (dev) || !dev->link_active_reporting)
@@ -96,10 +92,9 @@ int pcie_failed_link_retrain(struct pci_dev *dev)pcie_capability_read_word (dev,PCI_EXP_LNKCTL2 , &lnkctl2);pcie_capability_read_word (dev,PCI_EXP_LNKSTA , &lnksta); + oldlnkctl2 = lnkctl2;if ((lnksta & (PCI_EXP_LNKSTA_LBMS |PCI_EXP_LNKSTA_DLLLA )) ==PCI_EXP_LNKSTA_LBMS ) { -u16 oldlnkctl2 = lnkctl2; -pci_info (dev,"broken device, retraining non-functional downstream link at 2.5GT/s\n" ); lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS ;
@@ -107,35 +102,29 @@ int pcie_failed_link_retrain(struct pci_dev *dev)pcie_capability_write_word (dev,PCI_EXP_LNKCTL2 , lnkctl2); ret =pcie_retrain_link (dev, false); -if (ret) { -pci_info (dev,"retraining failed\n" ); -pcie_capability_write_word (dev,PCI_EXP_LNKCTL2 , - oldlnkctl2); -pcie_retrain_link (dev, true); -return ret; - } - -pcie_capability_read_word (dev,PCI_EXP_LNKSTA , &lnksta); +if (ret) + goto err; } -if ((lnksta &PCI_EXP_LNKSTA_DLLLA ) && - (lnkctl2 &PCI_EXP_LNKCTL2_TLS ) ==PCI_EXP_LNKCTL2_TLS_2_5GT && -pci_match_id (ids, dev)) { -u32 lnkcap; - +pcie_capability_read_dword (dev,PCI_EXP_LNKCAP , &lnkcap); +if ((lnkctl2 &PCI_EXP_LNKCTL2_TLS ) ==PCI_EXP_LNKCTL2_TLS_2_5GT && + (lnkcap &PCI_EXP_LNKCAP_SLS ) !=PCI_EXP_LNKCAP_SLS_2_5GB ) {pci_info (dev,"removing 2.5GT/s downstream link speed restriction\n" ); -pcie_capability_read_dword (dev,PCI_EXP_LNKCAP , &lnkcap); lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS ; lnkctl2 |= lnkcap &PCI_EXP_LNKCAP_SLS ;pcie_capability_write_word (dev,PCI_EXP_LNKCTL2 , lnkctl2); ret =pcie_retrain_link (dev, false); -if (ret) { -pci_info (dev,"retraining failed\n" ); -return ret; - } +if (ret) + goto err; } +return ret; +err: +pci_info (dev,"retraining failed\n" ); +pcie_capability_write_word (dev,PCI_EXP_LNKCTL2 , oldlnkctl2); + +pcie_retrain_link (dev, true);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 260/1266 udf: validate free block extents against the partition length
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 5f0419457f89dce1a3f1c8e62a3adf2f39ab8168 upstream.
udf_free_blocks() checks the logical block number and count against the partition length, but drops the extent offset from that final bound. A crafted extent can pass the guard while logicalBlockNum + offset + count points past the partition, which later indexes past the space bitmap array.
A single ftruncate(2) on a file backed by such an extent reliably panics the kernel. This is a local availability issue. On desktop systems where UDisks/polkit allows the active user to mount removable UDF media without CAP_SYS_ADMIN, an unprivileged local user can supply the crafted filesystem and trigger the panic by truncating a writable file on it. Systems that require root or CAP_SYS_ADMIN to mount the image have a higher prerequisite.
No confidentiality or integrity impact is claimed: the reproduced primitive is an out-of-bounds read of a bitmap pointer slot followed by a kernel panic.
Use the already computed logicalBlockNum + offset + count value for the partition length check. Also make load_block_bitmap() reject an out-of-range block group before indexing s_block_bitmap[], so corrupted callers cannot walk past the flexible array.
--- fs/udf/balloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/udf/balloc.c +3 -2
@@ -82,8 +82,9 @@ static int __load_block_bitmap(struct suint nr_groups = bitmap->s_nr_groups;if (block_group >= nr_groups) { -udf_debug ("block_group (%u) > nr_groups (%d)\n" , +udf_debug ("block_group (%u) >= nr_groups (%d)\n" , block_group, nr_groups); +return -EFSCORRUPTED ; }if (bitmap->s_block_bitmap[block_group]) {
@@ -679,7 +680,7 @@ void udf_free_blocks(struct super_blockif (check_add_overflow (bloc->logicalBlockNum, offset, &blk) ||check_add_overflow (blk, count, &blk) || - bloc->logicalBlockNum + count > map->s_partition_len) { + blk > map->s_partition_len) { udf_debug("Invalid request to free blocks: (%d, %u), off %u, " "len %u, partition len %u\n", partition, bloc->logicalBlockNum, offset, count,
Greg Kroah-Hartman
maintainerPATCH 261/1266 udf: validate VAT header length against the VAT inode size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit d8202786b3d75125c84ebc4de6d946f92fde0ee8 upstream.
udf_load_vat() takes the virtual partition's start offset straight from the on-disk VAT 2.0 header without checking it against the VAT inode size:
map->s_type_specific.s_virtual.s_start_offset = le16_to_cpu(vat20->lengthHeader); map->s_type_specific.s_virtual.s_num_entries = (sbi->s_vat_inode->i_size - map->s_type_specific.s_virtual.s_start_offset) >> 2;
lengthHeader is a fully attacker-controlled 16-bit value. If it exceeds the VAT inode size, the s_num_entries subtraction underflows to a huge count, which defeats the "block > s_num_entries" bound in udf_get_pblock_virt15(); and on the ICB-inline path that function reads
((__le32 *)(iinfo->i_data + s_start_offset))[block]
so a large s_start_offset indexes past the inode's in-ICB data. Mounting a crafted UDF image with a virtual (VAT) partition then triggers an out-of-bounds read.
Reject a VAT whose header length does not leave room for at least one entry within the VAT inode.
--- fs/udf/super.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/udf/super.c +8 -0
@@ -1232,6 +1232,14 @@ static int udf_load_vat(struct super_blo map->s_type_specific.s_virtual.s_start_offset =le16_to_cpu (vat20->lengthHeader); +if (map->s_type_specific.s_virtual.s_start_offset + > sbi->s_vat_inode->i_size) { +udf_err (sb,"Corrupted VAT header length %u (VAT inode size %lld)\n" , + map->s_type_specific.s_virtual.s_start_offset, + sbi->s_vat_inode->i_size); +brelse (bh); +return -EFSCORRUPTED ; + } map->s_type_specific.s_virtual.s_num_entries = (sbi->s_vat_inode->i_size - map->s_type_specific.s_virtual.
Greg Kroah-Hartman
maintainerPATCH 262/1266 udf: validate sparing table length as an entry count, not a byte count
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 3ec997bd5508e9b25210b5bbec89031629cdb093 upstream.
udf_load_sparable_map() accepts a sparing table when
sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > sb->s_blocksize
is false, i.e. it treats reallocationTableLen as a number of BYTES that must fit in the block. But the table is walked as an array of 8-byte sparingEntry elements:
for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) {
struct sparingEntry *entry = &st->mapEntry[i];
... entry->origLocation ...
}in udf_get_pblock_spar15() and udf_relocate_blocks(). A reallocationTableLen of N therefore passes the check whenever sizeof(*st) + N <= blocksize, yet the consumers index sizeof(*st) + N * sizeof(struct sparingEntry) bytes -- up to ~8x the block. On a crafted UDF image this is an out-of-bounds read in udf_get_pblock_spar15(); udf_relocate_blocks() additionally feeds the same length to udf_update_tag(), whose crc_itu_t() reads far past the block, and its memmove() through st->mapEntry[] is an out-of-bounds write.
Validate reallocationTableLen as the entry count it is, with struct_size().
--- fs/udf/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/udf/super.c +2 -1
@@ -1395,7 +1395,8 @@ static int udf_load_sparable_map(structif (ident !=0 ||strncmp (st->sparingIdent.ident,UDF_ID_SPARING ,strlen (UDF_ID_SPARING )) || -sizeof (*st) +le16_to_cpu (st->reallocationTableLen) > +struct_size (st, mapEntry, +le16_to_cpu (st->reallocationTableLen)) > sb->s_blocksize) {brelse (bh);continue ;
Greg Kroah-Hartman
maintainerPATCH 263/1266 hwrng: jh7110 - fix refcount leak in starfive_trng_read()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit 8d13f7a8450206e3f820cdb26e33e91d181071b4 upstream.
The starfive_trng_read() function acquires a runtime PM reference via pm_runtime_get_sync() but fails to release it on two error paths. If starfive_trng_wait_idle() or starfive_trng_cmd() returns an error, the function exits without calling pm_runtime_put_sync_autosuspend(), leaving the runtime PM usage counter permanently elevated and preventing the device from entering runtime suspend.
Refactor the function to use a unified error path that calls pm_runtime_put_sync_autosuspend() before returning.
--- drivers/char/hw_random/jh7110-trng.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/char/hw_random/jh7110-trng.c +8 -5
@@ -256,19 +256,22 @@ static int starfive_trng_read(struct hwrif (wait) { ret =starfive_trng_wait_idle (trng); -if (ret) -return -ETIMEDOUT ; +if (ret) { + ret = -ETIMEDOUT ; + goto out_put; + } } ret =starfive_trng_cmd (trng,STARFIVE_CTRL_GENE_RANDNUM , wait);if (ret) -return ret; + goto out_put;memcpy_fromio (buf, trng->base +STARFIVE_RAND0 , max); + ret = max; +out_put:pm_runtime_put_sync_autosuspend (trng->dev); - -return max; +return ret; }static int starfive_trng_probe (struct platform_device *pdev)
Greg Kroah-Hartman
maintainerPATCH 264/1266 dm-ioctl: report an error if a device has no table
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit 457e32348d606a77f9b20e25e989734189834c07 upstream.
When we send a message to a device that has no table, the return code was not set. The code would return "2", which is not considered a valid return value.
--- drivers/md/dm-ioctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/md/dm-ioctl.c +4 -1
@@ -1806,8 +1806,11 @@ static int target_message(struct file *f goto out_argv; table =dm_get_live_table (md, &srcu_idx); -if (!table) +if (!table) { +DMERR ("The device has no table." ); + r = -EINVAL ; goto out_table; + }if (dm_deleting_md (md)) { r = -ENXIO ;
Greg Kroah-Hartman
maintainerPATCH 265/1266 nvme-multipath: set BIO_REMAPPED on bios remapped to per-path namespace disks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Achkinazi, Igor <[email protected]>
commit 88bac2c1a72b8f4f71e9845699aa872df04e5850 upstream.
When nvme_ns_head_submit_bio() remaps a bio from the multipath head to a per-path namespace, bio_set_dev() clears BIO_REMAPPED. The remapped bio is then resubmitted through submit_bio_noacct() which calls bio_check_eod() because BIO_REMAPPED is not set.
This races with nvme_ns_remove() which zeroes the per-path capacity before synchronize_srcu():
CPU 0 (IO submission)
---------------------
srcu_read_lock()
nvme_find_path() -> ns
[NVME_NS_READY is set]
CPU 1 (namespace removal)
-------------------------
clear_bit(NVME_NS_READY)
set_capacity(ns->disk, 0)
synchronize_srcu() <- blocks
CPU 0 (IO submission)
---------------------
bio_set_dev(bio, ns->disk->part0)
[clears BIO_REMAPPED]
submit_bio_noacct(bio)
-> bio_check_eod() sees capacity=0
-> bio fails with IO errorThe SRCU read lock prevents synchronize_srcu() from completing, but does not prevent set_capacity(0) from executing. The bio fails the EOD check before it reaches the NVMe driver, so nvme_failover_req() never gets a chance to redirect it to another path of multipath. IO errors are reported to the application despite another path being available.
On older kernels (before commit 0b64682e78f7 "block: skip unnecessary checks for split bio"), the same race was also reachable through split remainders resubmitted via submit_bio_noacct().
Fix this by setting BIO_REMAPPED after bio_set_dev() in nvme_ns_head_submit_bio(). This skips bio_check_eod() on the per-path device; the EOD check already passed on the multipath head.
NVMe per-path namespace devices are always whole disks (bd_partno=0), so the blk_partition_remap() skip also gated by BIO_REMAPPED is a no-op. The flag does not persist across failover and cannot go stale if the namespace geometry changes between attempts: nvme_failover_req() calls bio_set_dev() to redirect the bio back to the multipath head, which clears BIO_REMAPPED. When nvme_requeue_work() resubmits through submit_bio_noacct(), bio_check_eod() runs normally against the current capacity.
Same approach as commit 3a905c37c351 ("block: skip bio_check_eod for partition-remapped bios").
--- drivers/nvme/host/multipath.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/nvme/host/multipath.c +6 -0
@@ -467,6 +467,12 @@ static void nvme_ns_head_submit_bio(stru ns =nvme_find_path (head);if (likely (ns)) {bio_set_dev (bio, ns->disk->part0); +/* +* Use BIO_REMAPPED to skip bio_check_eod() when this bio +* enters submit_bio_noacct() for the per-path device. The EOD +* check already passed on the multipath head. +*/ +bio_set_flag (bio,BIO_REMAPPED ); bio->bi_opf |=REQ_NVME_MPATH ;trace_block_bio_remap (bio,disk_devt (ns->head->disk), bio->bi_iter.bi_sector);
Greg Kroah-Hartman
maintainerPATCH 266/1266 btrfs: do not trim a device which is not writeable
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 1b1937eb08f51319bf71575484cde2b8c517aedc upstream.
[BUG]
There is a bug report that btrfs/242 can randomly fail with the following NULL pointer dereference:
run fstests btrfs/242 at 2026-06-01 10:25:08
BTRFS: device fsid d4d7f234-487c-4787-88e4-47a8b68c9874 devid 1 transid 9 /dev/sdc (8:32) scanned by mount (122609) BTRFS info (device sdc): first mount of filesystem d4d7f234-487c-4787-88e4-47a8b68c9874
BTRFS info (device sdc): using crc32c checksum algorithm
BTRFS warning (device sdc): devid 2 uuid fbe72d72-3272-482d-80fb-ab88ed398192 is missing
BTRFS warning (device sdc): devid 2 uuid fbe72d72-3272-482d-80fb-ab88ed398192 is missing
BTRFS info (device sdc): allowing degraded mounts
BTRFS info (device sdc): turning on async discard
BTRFS info (device sdc): enabling free space tree
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000018 user pgtable: 4k pages, 48-bit VAs, pgdp=000000013fd6b000 CPU: 4 UID: 0 PID: 122625 Comm: fstrim Not tainted 7.0.10-2-default #1 PREEMPT(full) openSUSE Tumbleweed e9a5f6b24978fba3bf015a992f865837fdfff3dd Hardware name: QEMU KVM Virtual Machine, BIOS edk2-20250812-19.fc42 08/12/2025 pstate: 01400005 (nzcv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : btrfs_trim_fs+0x34c/0xa00 [btrfs] lr : btrfs_trim_fs+0x1f0/0xa00 [btrfs] Call trace: btrfs_trim_fs+0x34c/0xa00 [btrfs f02c1d570ceea621c69d302ba75dd61868083840] (P) btrfs_ioctl_fitrim+0xe8/0x178 [btrfs f02c1d570ceea621c69d302ba75dd61868083840] btrfs_ioctl+0xdd4/0x2bd8 [btrfs f02c1d570ceea621c69d302ba75dd61868083840] __arm64_sys_ioctl+0xac/0x108 invoke_syscall.constprop.0+0x5c/0xd0 el0_svc_common.constprop.0+0x40/0xf0 do_el0_svc+0x24/0x40 el0_svc+0x40/0x1d0 el0t_64_sync_handler+0xa0/0xe8 el0t_64_sync+0x1b0/0x1b8 Code: 17ffff83 f94017e0 f9002be0 f9402ea0 (f9400c00) ---[ end trace 0000000000000000 ]---
Also the reporter is very kind to test the following ASSERT() added to btrfs_trim_free_extents_throttle():
ASSERT(device->bdev, "devid=%llu path=%s dev_state=0x%lx\n", device->devid, btrfs_dev_name(device), device->dev_state);
And it shows the following output:
assertion failed: device->bdev, in extent-tree.c:6630 (devid=2 path=/dev/sdd dev_state=0x82)
Which means the device->bdev is NULL, and the dev_state is BTRFS_DEV_STATE_IN_FS_METADATA | BTRFS_DEV_STATE_ITEM_FOUND, without BTRFS_DEV_STATE_WRITEABLE flag set.
[CAUSE]
The pc points to the following call chain:
btrfs_trim_fs()
|- btrfs_trim_free_extents()
|- btrfs_trim_free_extents_throttle()
|- bdev_max_discard_sectors(device->bdev)So the NULL pointer dereference is caused by device->bdev being NULL.
This looks impossible by a quick glance, as just before calling btrfs_trim_free_extents_throttle(), we have skipped any device that has BTRFS_DEV_STATE_MISSING flag set.
However in this particular case, there is a window where the missing device is later re-scanned, causing btrfs to remove the BTRFS_DEV_STATE_MISSING flag:
btrfs_control_ioctl()
|- btrfs_scan_one_device()
|- device_list_add()
|- rcu_assign_pointer(device->name, name);
| This updates the missing device's path to the new good path.
|
|- clear_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)
This removes the BTRFS_DEV_STATE_MISSING flag.This allows the missing device to re-appear and clear the BTRFS_DEV_STATE_MISSING flag. However the device still does not have the BTRFS_DEV_STATE_WRITEABLE flag set, nor is its bdev pointer updated.
The bdev pointer remains NULL, triggering the crash later.
[FIX]
This is a big de-synchronization between BTRFS_DEV_STATE_MISSING and device->bdev pointer, and shows a gap in btrfs's re-appearing-device handling.
The proper handling of re-appearing device will need quite some extra work, which is out of the context of this small fix.
Thankfully the regular bbio submission path has already handled it well by checking if the device->bdev is NULL before submitting.
So here we just fix the crash by checking if the device is writeable and has a bdev pointer before calling bdev_max_discard_sectors().
--- fs/btrfs/extent-tree.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
fs/btrfs/extent-tree.c +8 -4
@@ -6053,12 +6053,16 @@ static int btrfs_trim_free_extents(struc *trimmed =0 ; -/* Discard not supported = nothing to do. */ -if (!bdev_max_discard_sectors (device->bdev)) +/* +* The caller only filters out MISSING devices, but a device that was +* missing at mount and later rescanned has MISSING cleared while bdev +* is still NULL and WRITEABLE is still unset. Skip those here. +*/ +if (!test_bit (BTRFS_DEV_STATE_WRITEABLE , &device->dev_state) || !device->bdev)return 0 ; -/* Not writable = nothing to do. */ -if (!test_bit (BTRFS_DEV_STATE_WRITEABLE , &device->dev_state)) +/* Discard not supported = nothing to do. */ +if (!bdev_max_discard_sectors (device->bdev))return 0 ;/* No free space = nothing to do. */
Greg Kroah-Hartman
maintainerPATCH 267/1266 partitions: aix: bound the pp_count scan to the ppe array
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 2dc0bfd2fe355fb930de63c2f2eb8ced8570c579 upstream.
aix_partition() reads the physical volume descriptor into a fixed-size struct pvd and then scans its physical-partition-extent array:
int numpps = be16_to_cpu(pvd->pp_count);
...
for (i = 0; i < numpps; i += 1) {
struct ppe *p = pvd->ppe + i;
...
lp_ix = be16_to_cpu(p->lp_ix);pvd points at a single kmalloc()'d struct pvd whose ppe[] member holds a fixed ARRAY_SIZE(pvd->ppe) (1016) entries, but the loop runs up to the on-disk pp_count. pp_count is an unvalidated __be16 read straight from the descriptor, so a crafted AIX image with pp_count larger than 1016 drives the loop to read pvd->ppe[i] past the end of the allocation (up to 65535 entries, ~2 MB out of bounds).
The partition scan runs without mounting anything, when a block device with a crafted AIX/IBM partition table appears (an attacker-supplied image attached with losetup -P, or a device auto-scanned by udev), via msdos_partition() -> aix_partition().
Clamp the scan to the number of entries the ppe[] array can hold.
--- block/partitions/aix.c | 9 +++++++++ 1 file changed, 9 insertions(+)
block/partitions/aix.c +9 -0
@@ -228,6 +228,15 @@ int aix_partition(struct parsed_partitioint next_lp_ix =1 ;int lp_ix; +/* +* pvd was read into a fixed-size struct pvd whose ppe[] array +* holds ARRAY_SIZE(pvd->ppe) entries. pp_count is an +* unvalidated on-disk __be16, so clamp the scan to the array +* size to avoid walking past the allocation. +*/ +if (numpps >ARRAY_SIZE (pvd->ppe)) + numpps =ARRAY_SIZE (pvd->ppe); +for (i =0 ; i < numpps; i +=1 ) {struct ppe *p = pvd->ppe + i;unsigned int lv_ix;
Greg Kroah-Hartman
maintainerPATCH 268/1266 isofs: bound Rock Ridge symlink components to the SL record
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 5fa1d6a5ec2356d2107dead614437c66fa7138b1 upstream.
get_symlink_chunk() and the SL handling in parse_rock_ridge_inode_internal() walk the variable-length components of a Rock Ridge "SL" (symbolic link) record. Each component is a two-byte header (flags, len) followed by len bytes of text, so it occupies slp->len + 2 bytes. Both loops read slp->len and advance to the next component, and get_symlink_chunk() additionally does memcpy(rpnt, slp->text, slp->len), but neither checks that the component lies within the SL record before dereferencing it.
A crafted SL record whose component declares a len that runs past the record (rr->len) therefore triggers an out-of-bounds read of up to 255 bytes. When the record sits at the tail of its backing buffer - for example a small kmalloc()ed continuation block reached through a CE record - the read crosses the allocation; get_symlink_chunk() then copies the out-of-bounds bytes into the symlink body returned to user space by readlink(), disclosing adjacent kernel memory.
ISO 9660 images are routinely mounted from untrusted removable media - desktop environments auto-mount them (e.g. via udisks2) without CAP_SYS_ADMIN - so the record contents are attacker-controlled.
Reject any component that does not fit in the remaining record bytes before using it. In get_symlink_chunk() return NULL, like the existing output-buffer (plimit) checks, so a malformed record makes readlink() fail with -EIO rather than silently returning a truncated target; in parse_rock_ridge_inode_internal() stop the inode-size walk.
--- fs/isofs/rock.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
fs/isofs/rock.c +11 -0
@@ -462,6 +462,9 @@ repeat: inode->i_size = symlink_len;while (slen >1 ) { rootflag =0 ; +/* keep the component within the SL record */ +if (slp->len +2 > slen) + goto eio;switch (slp->flags & ~1 ) {case 0 : inode->i_size +=
@@ -617,6 +620,14 @@ static char *get_symlink_chunk(char *rpn slp = &rr->u.SL.link;while (slen >1 ) { rootflag =0 ; +/* +* A component is slp->len + 2 bytes (a two-byte header plus +* len bytes of text). If it does not fit in the bytes left in +* the SL record the record is malformed: fail like the plimit +* checks below so readlink() returns -EIO, not a truncated path. +*/ +if (slp->len +2 > slen) +return NULL ;switch (slp->flags & ~1 ) {case 0 :if (slp->len > plimit - rpnt)
Greg Kroah-Hartman
maintainerPATCH 269/1266 crypto: af_alg - Remove zero-copy support from skcipher and aead
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit ffdd2bc378953b525aca61902534e753f1f8e734 upstream.
The zero-copy support is one of the riskiest aspects of AF_ALG. It allows userspace to request cryptographic operations directly on pagecache pages of files like the 'su' binary. It also allows userspace to concurrently modify the memory which is being operated on, a recipe for TOCTOU vulnerabilities.
While zero-copy support is more valuable in other areas of the kernel like the frequently used networking and file I/O code, it has far less value in AF_ALG, which is a niche UAPI. AF_ALG primarily just exists for backwards compatibility with a small set of userspace programs such as 'iwd' that haven't yet been fixed to use userspace crypto code.
Originally AF_ALG was intended to be used to access hardware crypto accelerators. However, it isn't an efficient interface for that anyway, and it turned out to be rarely used in this way in practice.
Thus, the risks of the zero-copy support in AF_ALG vastly outweigh its benefits. Let's just remove it.
This commit removes it from the "skcipher" and "aead" algorithm types. "hash" will be handled separately.
This is a soft break, not a hard break. Even after this commit, it still works to use splice() or sendfile() to transfer data to an AF_ALG request socket from a pipe or any file, respectively. What changes is just that the kernel now makes an internal, stable copy of the data before doing the crypto operation. So performance is slightly reduced, but the UAPI isn't broken. And, very importantly, it's much safer.
Tested with libkcapi/test.sh. All its test cases still pass. I also verified that this would have prevented the copy.fail exploit as well. I also used a custom test program to verify that sendfile() still works.
--- Documentation/crypto/userspace-if.rst | 31 +------------- crypto/af_alg.c | 71 +++++++++++----------------------- crypto/algif_aead.c | 8 +-- 3 files changed, 32 insertions(+), 78 deletions(-)
Documentation/crypto/userspace-if.rst +4 -27
@@ -328,33 +328,10 @@ CRYPTO_USER_API_RNG_CAVP option: Zero-Copy Interface ------------------- -In addition to the send/write/read/recv system call family, the AF_ALG -interface can be accessed with the zero-copy interface of -splice/vmsplice. As the name indicates, the kernel tries to avoid a copy -operation into kernel space. - -The zero-copy operation requires data to be aligned at the page -boundary. Non-aligned data can be used as well, but may require more -operations of the kernel which would defeat the speed gains obtained -from the zero-copy interface. - -The system-inherent limit for the size of one zero-copy operation is 16 -pages. If more data is to be sent to AF_ALG, user space must slice the -input into segments with a maximum size of 16 pages. - -Zero-copy can be used with the following code example (a complete -working example is provided with libkcapi): - -:: - - int pipes[2]; - - pipe(pipes); - /* input data in iov */ - vmsplice(pipes[1], iov, iovlen, SPLICE_F_GIFT); - /* opfd is the file descriptor returned from accept() system call */ - splice(pipes[0], NULL, opfd, NULL, ret, 0); - read(opfd, out, outlen); +AF_ALG used to have zero-copy support, but it was removed due to it being a +frequent source of vulnerabilities. For backwards compatibility the splice() +and sendfile() system calls are still supported, but the kernel will make an +internal copy of the data before passing it to the crypto code. Setsockopt Interface
crypto/af_alg.c +24 -47
91 lines not on this page · raw message
crypto/algif_aead.c +4 -4
@@ -9,10 +9,10 @@* The following concept of the memory management is used: * * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is -* filled by user space with the data submitted via sendmsg (maybe with -* MSG_SPLICE_PAGES). Filling up the TX SGL does not cause a crypto operation -* -- the data will only be tracked by the kernel. Upon receipt of one recvmsg -* call, the caller must provide a buffer which is tracked with the RX SGL. +* filled by user space with the data submitted via sendmsg. Filling up the TX +* SGL does not cause a crypto operation -- the data will only be tracked by the +* kernel. Upon receipt of one recvmsg call, the caller must provide a buffer +* which is tracked with the RX SGL. * * During the processing of the recvmsg operation, the cipher request is * allocated and prepared. As part of the recvmsg operation, the processed
Greg Kroah-Hartman
maintainerPATCH 270/1266 crypto: caam - use print_hex_dump_devel to guard key hex dumps
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit 3f57657b6ea23f933371f2c2846322f441773cee upstream.
Use print_hex_dump_devel() for dumping sensitive key material in *_setkey() and gen_split_key() to avoid leaking secrets at runtime when CONFIG_DYNAMIC_DEBUG is enabled.
--- drivers/crypto/caam/caamalg.c | 12 ++++++------ drivers/crypto/caam/caamalg_qi.c | 12 ++++++------ drivers/crypto/caam/caamhash.c | 4 ++-- drivers/crypto/caam/key_gen.c | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-)
drivers/crypto/caam/caamalg.c +6 -6
@@ -597,7 +597,7 @@ static int aead_setkey(struct crypto_aeadev_dbg (jrdev,"keylen %d enckeylen %d authkeylen %d\n" , keys.authkeylen + keys.enckeylen, keys.enckeylen, keys.authkeylen); - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );/*
@@ -633,7 +633,7 @@ static int aead_setkey(struct crypto_aeadma_sync_single_for_device (jrdev, ctx->key_dma, ctx->adata.keylen_pad + keys.enckeylen, ctx->dir); - print_hex_dump_debug("ctx.key@"__stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@"__stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , ctx->key, ctx->adata.keylen_pad + keys.enckeylen,1 );
@@ -674,7 +674,7 @@ static int gcm_setkey(struct crypto_aeadif (err)return err; - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -695,7 +695,7 @@ static int rfc4106_setkey(struct crypto_if (err)return err; - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -721,7 +721,7 @@ static int rfc4543_setkey(struct crypto_if (err)return err; - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -748,7 +748,7 @@ static int skcipher_setkey(struct cryptou32 *desc;const bool is_rfc3686 = alg->caam.rfc3686; - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 ); ctx->cdata.keylen = keylen;
drivers/crypto/caam/caamalg_qi.c +6 -6
@@ -212,7 +212,7 @@ static int aead_setkey(struct crypto_aeadev_dbg (jrdev,"keylen %d enckeylen %d authkeylen %d\n" , keys.authkeylen + keys.enckeylen, keys.enckeylen, keys.authkeylen); - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );/*
@@ -248,7 +248,7 @@ static int aead_setkey(struct crypto_aea ctx->adata.keylen_pad + keys.enckeylen, ctx->dir); - print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , ctx->key, ctx->adata.keylen_pad + keys.enckeylen,1 );
@@ -371,7 +371,7 @@ static int gcm_setkey(struct crypto_aeadif (ret)return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -475,7 +475,7 @@ static int rfc4106_setkey(struct crypto_if (ret)return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -581,7 +581,7 @@ static int rfc4543_setkey(struct crypto_if (ret)return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -631,7 +631,7 @@ static int skcipher_setkey(struct cryptoconst bool is_rfc3686 = alg->caam.rfc3686;int ret =0 ; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 ); ctx->cdata.keylen = keylen;
drivers/crypto/caam/caamhash.c +2 -2
@@ -505,7 +505,7 @@ static int axcbc_setkey(struct crypto_ah DMA_TO_DEVICE); ctx->adata.keylen = keylen; - print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ", + print_hex_dump_devel("axcbc ctx.key@" __stringify(__LINE__)" : ",DUMP_PREFIX_ADDRESS ,16 ,4 , ctx->key, keylen,1 );return axcbc_set_sh_desc (ahash);
@@ -525,7 +525,7 @@ static int acmac_setkey(struct crypto_ah ctx->adata.key_virt = key; ctx->adata.keylen = keylen; - print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ", + print_hex_dump_devel("acmac ctx.key@" __stringify(__LINE__)" : ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );return acmac_set_sh_desc (ahash);
drivers/crypto/caam/key_gen.c +2 -2
@@ -58,7 +58,7 @@ int gen_split_key(struct device *jrdev,dev_dbg (jrdev,"split keylen %d split keylen padded %d\n" , adata->keylen, adata->keylen_pad); - print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key_in, keylen,1 );if (local_max > max_keylen)
@@ -113,7 +113,7 @@ int gen_split_key(struct device *jrdev,wait_for_completion (&result.completion); ret = result.err; - print_hex_dump_debug("ctx.key@"__stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@"__stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key_out, adata->keylen_pad,1 ); }
Greg Kroah-Hartman
maintainerPATCH 271/1266 crypto: caam - use print_hex_dump_devel to guard key hex dumps again
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit 8005dc808bcce7d6cc2ae015a3cde1683bee602d upstream.
Use print_hex_dump_devel() for dumping sensitive key material in *_setkey() to avoid leaking secrets at runtime when CONFIG_DYNAMIC_DEBUG is enabled.
--- drivers/crypto/caam/caamalg_qi2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/crypto/caam/caamalg_qi2.c +6 -6
@@ -299,7 +299,7 @@ static int aead_setkey(struct crypto_aeadev_dbg (dev,"keylen %d enckeylen %d authkeylen %d\n" , keys.authkeylen + keys.enckeylen, keys.enckeylen, keys.authkeylen); - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 ); ctx->adata.keylen = keys.authkeylen;
@@ -313,7 +313,7 @@ static int aead_setkey(struct crypto_aeamemcpy (ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen);dma_sync_single_for_device (dev, ctx->key_dma, ctx->adata.keylen_pad + keys.enckeylen, ctx->dir); - print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , ctx->key, ctx->adata.keylen_pad + keys.enckeylen,1 );
@@ -730,7 +730,7 @@ static int gcm_setkey(struct crypto_aead ret =aes_check_keylen (keylen);if (ret)return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -826,7 +826,7 @@ static int rfc4106_setkey(struct crypto_if (ret)return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -925,7 +925,7 @@ static int rfc4543_setkey(struct crypto_if (ret)return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 );memcpy (ctx->key, key, keylen);
@@ -953,7 +953,7 @@ static int skcipher_setkey(struct cryptou32 *desc;const bool is_rfc3686 = alg->caam.rfc3686; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ",DUMP_PREFIX_ADDRESS ,16 ,4 , key, keylen,1 ); ctx->cdata.keylen = keylen;
Greg Kroah-Hartman
maintainerPATCH 272/1266 crypto: ecc - Fix carry overflow in vli multiplication
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anastasia Tishchenko <[email protected]>
commit 27b536a2ec8e2f85a0380c2d13c9ecbc7aaab406 upstream.
The carry flag calculation fails when r01.m_high is saturated (0xFFFFFFFFFFFFFFFF) and addition of lower bits overflows.
The condition (r01.m_high < product.m_high) doesn't handle the case where r01.m_high == product.m_high and an additional carry exists from lower-bit overflow.
When commit 3c4b23901a0c ("crypto: ecdh - Add ECDH software support") introduced crypto/ecc.c, it split the muladd() function in the micro-ecc library into separate mul_64_64() and add_128_128() helpers. It seems the check got lost in translation.
Add proper handling for this boundary by accounting for the carry from the lower addition.
--- crypto/ecc.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-)
crypto/ecc.c +20 -11
@@ -400,14 +400,26 @@ static uint128_t mul_64_64(u64 left, u64return result; } -static uint128_t add_128_128 (uint128_t a,uint128_t b) +/* Calculate addition with overflow checking. Returns true on wrap-around, +* false otherwise. +*/ +static bool check_add_128_128_overflow (uint128_t *result,uint128_t a, +uint128_t b) { -uint128_t result; +bool carry; - result.m_low = a.m_low + b.m_low; - result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low); + result->m_low = a.m_low + b.m_low; + carry = (result->m_low < a.m_low); -return result; + result->m_high = a.m_high + b.m_high + carry; + +/* Using constant-time bitwise arithmetic to prevent timing +* side-channels. +*/ + carry = (result->m_high < a.m_high) | + ((result->m_high == a.m_high) & carry); + +return carry; } static void vli_mult(u64 *result, const u64 *left, const u64 *right,
@@ -432,9 +444,7 @@ static void vli_mult(u64 *result, constuint128_t product; product =mul_64_64 (left[i], right[k - i]); - - r01 =add_128_128 (r01, product); - r2 += (r01.m_high < product.m_high); + r2 +=check_add_128_128_overflow (&r01, r01, product); } result[k] = r01.m_low;
@@ -457,7 +467,7 @@ static void vli_umult(u64 *result, constuint128_t product; product =mul_64_64 (left[k], right); - r01 =add_128_128 (r01, product); +check_add_128_128_overflow (&r01, r01, product);/* no carry */ result[k] = r01.m_low; r01.m_low = r01.m_high;
@@ -494,8 +504,7 @@ static void vli_square(u64 *result, cons product.m_low <<=1 ; } - r01 =add_128_128 (r01, product); - r2 += (r01.m_high < product.m_high); + r2 +=check_add_128_128_overflow (&r01, r01, product); } result[k] = r01.m_low;
Greg Kroah-Hartman
maintainerPATCH 273/1266 crypto: pcrypt - restore callback for non-parallel fallback
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruijie Li <[email protected]>
commit ed459fe319376e876de433d12b6c6772e612ca36 upstream.
pcrypt installs pcrypt_aead_done() on the child AEAD request before trying to submit it through padata. If padata_do_parallel() returns -EBUSY, pcrypt falls back to calling the child AEAD directly.
That fallback must not keep the padata completion callback. Otherwise an asynchronous completion runs pcrypt_aead_done() even though the request was never enrolled in padata.
Restore the original request callback and callback data before calling the child AEAD directly. This keeps the fallback path aligned with a direct AEAD request while leaving the parallel path unchanged.
--- crypto/pcrypt.c | 4 ++++ 1 file changed, 4 insertions(+)
crypto/pcrypt.c +4 -0
@@ -122,6 +122,8 @@ static int pcrypt_aead_encrypt(struct aereturn -EINPROGRESS ;if (err == -EBUSY ) {/* try non-parallel mode */ +aead_request_set_callback (creq, flags, req->base.complete, + req->base.data);return crypto_aead_encrypt (creq); }
@@ -173,6 +175,8 @@ static int pcrypt_aead_decrypt(struct aereturn -EINPROGRESS ;if (err == -EBUSY ) {/* try non-parallel mode */ +aead_request_set_callback (creq, flags, req->base.complete, + req->base.data);return crypto_aead_decrypt (creq); }
Greg Kroah-Hartman
maintainerPATCH 274/1266 crypto: drbg - Fix returning success on failure in CTR_DRBG
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit 39a31ad9e2a5ed7e9c9c6f711dca96c8c8f5f26b upstream.
drbg_ctr_generate() sometimes returns success when it fails, leaving the output buffer uninitialized. Fix it.
--- crypto/drbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
crypto/drbg.c +1 -1
@@ -603,7 +603,7 @@ static int drbg_ctr_generate(struct drbgif (addtl && !list_empty (addtl)) { ret =drbg_ctr_update (drbg, addtl,2 );if (ret) -return 0 ; +return ret; }/* 10.2.1.5.2 step 4.1 */
Greg Kroah-Hartman
maintainerPATCH 275/1266 crypto: drbg - Fix drbg_max_addtl() on 64-bit kernels
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit 6f49f00c981bbb9ef602966f19bfdbef46b681d2 upstream.
On 64-bit kernels, drbg_max_addtl() returns 2**35 bytes. That's too large, for two reasons:
1. SP800-90A says the maximum limit is 2**35 *bits*, not 2**35 bytes. So the implemented limit has confused bits and bytes.
2. When drbg_kcapi_hash() calls crypto_shash_update() on the additional information string, the length is implicitly cast to 'unsigned int'. That truncates the additional information string to U32_MAX bytes.
Fix the maximum additional information string length to always be U32_MAX - 1, causing an error to be returned for any longer lengths.
--- include/crypto/drbg.h | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-)
include/crypto/drbg.h +7 -11
@@ -171,19 +171,15 @@ static inline size_t drbg_max_request_byreturn (1 <<16 ); } +/* +* SP800-90A allows implementations to support additional info / personalization +* strings of up to 2**35 bits. Implementations can have a smaller maximum. We +* use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a +* size_t, allowing drbg_healthcheck_sanity() to verify its enforcement. +*/ static inline size_t drbg_max_addtl (struct drbg_state *drbg) { -/* SP800-90A requires 2**35 bytes additional info str / pers str */ -#if (__BITS_PER_LONG ==32 ) -/* -* SP800-90A allows smaller maximum numbers to be returned -- we -* return SIZE_MAX - 1 to allow the verification of the enforcement -* of this value in drbg_healthcheck_sanity. -*/ -return (SIZE_MAX -1 ); -#else -return (1UL <<35 ); -#endif +return U32_MAX -1 ; }static inline size_t drbg_max_requests (struct drbg_state *drbg)
Greg Kroah-Hartman
maintainerPATCH 276/1266 crypto: drbg - Fix the fips_enabled priority boost
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit a8a1f93080efc83a9ff8452954429ae379e9e614 upstream.
When fips_enabled=1, it seems to have been intended for one of the algorithms defined in crypto/drbg.c to be the highest priority "stdrng" algorithm, so that it is what is used by "stdrng" users.
However, the code only boosts the priority to 400, which is less than the priority 500 used in drivers/crypto/caam/caamprng.c. Thus, the CAAM RNG could be used instead.
Fix this by boosting the priority by 2000 instead of 200.
--- crypto/drbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
crypto/drbg.c +1 -1
@@ -2095,7 +2095,7 @@ static inline void __init drbg_fill_arra* it is selected. */ if (fips_enabled) - alg->base.cra_priority +=200 ; + alg->base.cra_priority +=2000 ; alg->base.cra_ctxsize =sizeof (struct drbg_state ); alg->base.cra_module =THIS_MODULE ;
Greg Kroah-Hartman
maintainerPATCH 277/1266 crypto: qat - validate RSA CRT component lengths
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Giovanni Cabiddu <[email protected]>
commit b3ac78756588059729b9195fcc9f4b37d54057a5 upstream.
The generic RSA key parser (rsa_helper.c) bounds each CRT component (p, q, dp, dq, qinv) by the modulus size n_sz, but qat_rsa_setkey_crt() allocates half-size DMA buffers (key_sz / 2) and right-aligns each component with:
memcpy(dst + half_key_sz - len, src, len)
When a CRT component is larger than half_key_sz the subtraction underflows and memcpy writes past the DMA buffer, causing memory corruption.
Add a len > half_key_sz check next to the existing !len check for each of the five CRT components so the driver falls back to the non-CRT path instead of writing out of bounds.
--- drivers/crypto/intel/qat/qat_common/qat_asym_algs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/crypto/intel/qat/qat_common/qat_asym_algs.c +5 -5
@@ -1032,7 +1032,7 @@ static void qat_rsa_setkey_crt(struct qa ptr = rsa_key->p; len = rsa_key->p_sz;qat_rsa_drop_leading_zeros (&ptr, &len); -if (!len) +if (!len || len > half_key_sz) goto err; ctx->p =dma_alloc_coherent (dev, half_key_sz, &ctx->dma_p,GFP_KERNEL );if (!ctx->p)
@@ -1043,7 +1043,7 @@ static void qat_rsa_setkey_crt(struct qa ptr = rsa_key->q; len = rsa_key->q_sz;qat_rsa_drop_leading_zeros (&ptr, &len); -if (!len) +if (!len || len > half_key_sz) goto free_p; ctx->q =dma_alloc_coherent (dev, half_key_sz, &ctx->dma_q,GFP_KERNEL );if (!ctx->q)
@@ -1054,7 +1054,7 @@ static void qat_rsa_setkey_crt(struct qa ptr = rsa_key->dp; len = rsa_key->dp_sz;qat_rsa_drop_leading_zeros (&ptr, &len); -if (!len) +if (!len || len > half_key_sz) goto free_q; ctx->dp =dma_alloc_coherent (dev, half_key_sz, &ctx->dma_dp,GFP_KERNEL );
@@ -1066,7 +1066,7 @@ static void qat_rsa_setkey_crt(struct qa ptr = rsa_key->dq; len = rsa_key->dq_sz;qat_rsa_drop_leading_zeros (&ptr, &len); -if (!len) +if (!len || len > half_key_sz) goto free_dp; ctx->dq =dma_alloc_coherent (dev, half_key_sz, &ctx->dma_dq,GFP_KERNEL );
@@ -1078,7 +1078,7 @@ static void qat_rsa_setkey_crt(struct qa ptr = rsa_key->qinv; len = rsa_key->qinv_sz;qat_rsa_drop_leading_zeros (&ptr, &len); -if (!len) +if (!len || len > half_key_sz) goto free_dq; ctx->qinv =dma_alloc_coherent (dev, half_key_sz, &ctx->dma_qinv,GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 278/1266 crypto: talitos - use dma_sync_single_for_cpu() before reading descriptor header
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit e17ff3d6ff907dc8406261e8fd3e1fc8a908f0f6 upstream.
In order to know if a descriptor has been processed by the device, the driver polls the FIFO to see if DESC_HDR_DONE is set on a descriptor header to confirm completion.
The current code does not make sure that the CPU gets up to date data before reading the descriptor.
Fix this by calling dma_sync_single_for_cpu() before reading memory written by the device.
--- drivers/crypto/talitos.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-)
drivers/crypto/talitos.c +20 -8
@@ -322,19 +322,31 @@ static int talitos_submit(struct devicereturn -EINPROGRESS ; } -static __be32 get_request_hdr (struct talitos_request *request,bool is_sec1) +static __be32 get_request_hdr (struct device *dev, +struct talitos_request *request,bool is_sec1) {struct talitos_edesc *edesc; -if (!is_sec1) +if (!is_sec1) { +dma_sync_single_for_cpu (dev, request->dma_desc, +TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); +return request->desc->hdr; + } -if (!request->desc->next_desc) +if (!request->desc->next_desc) { +dma_sync_single_for_cpu (dev, request->dma_desc, +TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL );return request->desc->hdr1; - - edesc = container_of(request->desc, struct talitos_edesc, desc); - -return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1; + }else { +dma_sync_single_for_cpu (dev, +be32_to_cpu (request->desc->next_desc), +TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); + edesc = container_of(request->desc, struct talitos_edesc, desc); + +return ((struct talitos_desc *)(edesc->buf + edesc->dma_len)) + ->hdr1; + } }/*
@@ -358,7 +370,7 @@ static void flush_channel(struct device/* descriptors with their done bits set don't get the error */ rmb (); - hdr =get_request_hdr (request, is_sec1); + hdr =get_request_hdr (dev, request, is_sec1);if ((hdr &DESC_HDR_DONE ) ==DESC_HDR_DONE ) status =0 ;
Greg Kroah-Hartman
maintainerPATCH 279/1266 crypto: talitos - add chaining of arbitrary number of descriptor for the SEC1
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit f126384ed55279c3b676f89d5ab547b8de8df782 upstream.
The SEC1 hardware can process a chain of descriptors without host intervention. Only the hash implementation currently use this feature, but with a chain of at most 2 descriptors added in commit 37b5e8897eb5 ("crypto: talitos - chain in buffered data for ahash on SEC1").
Add supports for chaining an arbitrary number of descriptors in a chain.
Adapt the ahash implementation to make it compatible.
--- drivers/crypto/talitos.c | 180 +++++++++++++++++++++++++++++++---------------- drivers/crypto/talitos.h | 2 2 files changed, 124 insertions(+), 58 deletions(-)
drivers/crypto/talitos.c +122 -58
@@ -273,7 +273,10 @@ static int talitos_submit(struct device void *context, int error), void *context) { + struct talitos_edesc *edesc = container_of(desc, struct talitos_edesc, desc);struct talitos_private *priv =dev_get_drvdata (dev); +dma_addr_t dma_desc, prev_dma_desc; +struct talitos_edesc *prev_edesc =NULL ;struct talitos_request *request;unsigned long flags;int head;
@@ -292,10 +295,31 @@ static int talitos_submit(struct device/* map descriptor and save caller data */ if (is_sec1) { - desc->hdr1 = desc->hdr; - request->dma_desc =dma_map_single (dev, &desc->hdr1, +while (edesc) { + edesc->desc.hdr1 = edesc->desc.hdr; + + dma_desc =dma_map_single (dev, &edesc->desc.hdr1, +TALITOS_DESC_SIZE , +DMA_BIDIRECTIONAL ); + +if (!prev_edesc) { + request->dma_desc = dma_desc; + goto next; + } + +/* Chain in any previous descriptors. */ + + prev_edesc->desc.next_desc =cpu_to_be32 (dma_desc); + +dma_sync_single_for_device (dev, prev_dma_desc,TALITOS_DESC_SIZE , -DMA_BIDIRECTIONAL ); +DMA_TO_DEVICE ); + +next: + prev_edesc = edesc; + prev_dma_desc = dma_desc; + edesc = edesc->next_desc; + } }else { request->dma_desc = dma_map_single(dev, desc, TALITOS_DESC_SIZE,
@@ -326,6 +350,7 @@ static __be32 get_request_hdr(struct dev struct talitos_request *request, bool is_sec1) {struct talitos_edesc *edesc; +dma_addr_t dma_desc;if (!is_sec1) { dma_sync_single_for_cpu(dev, request->dma_desc,
@@ -334,19 +359,17 @@ static __be32 get_request_hdr(struct devreturn request->desc->hdr; } -if (!request->desc->next_desc) { -dma_sync_single_for_cpu (dev, request->dma_desc, -TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); -return request->desc->hdr1; - }else { -dma_sync_single_for_cpu (dev, -be32_to_cpu (request->desc->next_desc), -TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); - edesc = container_of(request->desc, struct talitos_edesc, desc); - -return ((struct talitos_desc *)(edesc->buf + edesc->dma_len)) - ->hdr1; + edesc = container_of(request->desc, struct talitos_edesc, desc); + dma_desc = request->dma_desc; +while (edesc->next_desc) { + dma_desc =be32_to_cpu (edesc->desc.next_desc); + edesc = edesc->next_desc; } + +dma_sync_single_for_cpu (dev, dma_desc,TALITOS_DESC_SIZE , +DMA_BIDIRECTIONAL ); + +return edesc->desc.hdr1; }/*
@@ -356,6 +379,7 @@ static void flush_channel(struct device {struct talitos_private *priv =dev_get_drvdata (dev);struct talitos_request *request, saved_req; +struct talitos_edesc *edesc;unsigned long flags;int tail, status;bool is_sec1 =has_ftr_sec1 (priv);
@@ -380,9 +404,22 @@ static void flush_channel(struct deviceelse status = error; -dma_unmap_single (dev, request->dma_desc, -TALITOS_DESC_SIZE , -DMA_BIDIRECTIONAL ); +if (is_sec1) { +dma_unmap_single (dev, request->dma_desc, +TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); + edesc =container_of (request->desc, + struct talitos_edesc, desc); +while (edesc->next_desc) { +dma_unmap_single ( + dev,be32_to_cpu (edesc->desc.next_desc), +TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); + edesc = edesc->next_desc; + } + }else { +dma_unmap_single (dev, request->dma_desc, +TALITOS_DESC_SIZE , +DMA_BIDIRECTIONAL ); + }/* copy entries so we can call callback outside lock */ saved_req.desc = request->desc;
@@ -477,8 +514,12 @@ DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CHstatic __be32 current_desc_hdr (struct device *dev,int ch) {struct talitos_private *priv =dev_get_drvdata (dev); +bool is_sec1 =has_ftr_sec1 (priv); +struct talitos_request *request; +struct talitos_edesc *edesc;int tail, iter;dma_addr_t cur_desc; +__be32 hdr =0 ; cur_desc = ((u64 )in_be32 (priv->chan[ch].reg +TALITOS_CDPR )) <<32 ; cur_desc |=in_be32 (priv->chan[ch].reg +TALITOS_CDPR_LO );
@@ -489,27 +530,35 @@ static __be32 current_desc_hdr(struct de } tail = priv->chan[ch].tail; - iter = tail; -while (priv->chan[ch].fifo[iter].dma_desc != cur_desc && - priv->chan[ch].fifo[iter].desc->next_desc !=cpu_to_be32 (cur_desc)) { - iter = (iter +1 ) & (priv->fifo_len -1 ); -if (iter == tail) { -dev_err (dev,"couldn't locate current descriptor\n" ); -return 0 ; +do { + request = &priv->chan[ch].fifo[iter]; + +if (request->dma_desc == cur_desc) { + hdr = request->desc->hdr; + }else if (is_sec1) { + edesc =container_of (request->desc, + struct talitos_edesc, desc); +while (edesc->next_desc) { +if (edesc->desc.next_desc == +cpu_to_be32 (cur_desc)) { + hdr = edesc->next_desc->desc.hdr1; +break ; + } + edesc = edesc->next_desc; + } } - } -if (priv->chan[ch].fifo[iter].desc->next_desc ==cpu_to_be32 (cur_desc)) { -struct talitos_edesc *edesc; +if (hdr) +break ; - edesc =container_of (priv->chan[ch].fifo[iter].desc, - struct talitos_edesc, desc); -return ((struct talitos_desc *) - (edesc->buf + edesc->dma_len))->hdr; - } + iter = (iter +1 ) & (priv->fifo_len -1 ); + }while (iter != tail); + +if (!hdr) +dev_err (dev,"couldn't locate current descriptor\n" ); -return priv->chan[ch].fifo[iter].desc->hdr; +return hdr; }/*
@@ -1408,10 +1457,6 @@ static struct talitos_edesc *talitos_ede dma_len =0 ; } alloc_len += icv_stashing ? authsize :0 ; - -/* if its a ahash, add space for a second desc next to the first one */ -if (is_sec1 && !dst) - alloc_len +=sizeof (struct talitos_desc ); alloc_len += ivsize; edesc =kmalloc (ALIGN (alloc_len,dma_get_cache_alignment ()), flags);
@@ -1427,6 +1472,7 @@ static struct talitos_edesc *talitos_ede edesc->dst_nents = dst_nents; edesc->iv_dma = iv_dma; edesc->dma_len = dma_len; + edesc->next_desc =NULL ;if (dma_len) edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0], edesc->dma_len,
@@ -1727,8 +1773,10 @@ static void common_nonsnoop_hash_unmap(sstruct talitos_private *priv =dev_get_drvdata (dev);bool is_sec1 =has_ftr_sec1 (priv);struct talitos_desc *desc = &edesc->desc; -struct talitos_desc *desc2 = (struct talitos_desc *) - (edesc->buf + edesc->dma_len); +struct talitos_desc *desc2; + +if (desc->next_desc) + desc2 = &edesc->next_desc->desc;unmap_single_talitos_ptr (dev, &desc->ptr[5 ],DMA_FROM_DEVICE ); if (desc->next_desc &&
@@ -1756,10 +1804,17 @@ static void common_nonsnoop_hash_unmap(sif (edesc->dma_len)dma_unmap_single (dev, edesc->dma_link_tbl, edesc->dma_len,DMA_BIDIRECTIONAL ); +} -if (desc->next_desc) -dma_unmap_single (dev,be32_to_cpu (desc->next_desc), -TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); +static void free_edesc_list_from (struct talitos_edesc *edesc) +{ +struct talitos_edesc *next; + +while (edesc) { + next = edesc->next_desc; +kfree (edesc); + edesc = next; + } } static void ahash_done(struct device *dev,
@@ -1778,7 +1833,7 @@ static void ahash_done(struct device *de }common_nonsnoop_hash_unmap (dev, edesc, areq); -kfree (edesc); +free_edesc_list_from (edesc);if (err) {ahash_request_complete (areq, err);
@@ -1894,14 +1949,23 @@ static int common_nonsnoop_hash(struct ttalitos_handle_buggy_hash (ctx, edesc, &desc->ptr[3 ]);if (is_sec1 && req_ctx->nbuf && length) { -struct talitos_desc *desc2 = (struct talitos_desc *) - (edesc->buf + edesc->dma_len); -dma_addr_t next_desc; +struct talitos_edesc *edesc2; +struct talitos_desc *desc2; + + edesc2 =kzalloc (sizeof (*edesc2), + areq->base.flags &CRYPTO_TFM_REQ_MAY_SLEEP ? +GFP_KERNEL : +GFP_ATOMIC ); +if (!edesc2) { + ret = -ENOMEM ; + goto err; + } + edesc->next_desc = edesc2; + + desc2 = &edesc2->desc; -memset (desc2,0 ,sizeof (*desc2)); desc2->hdr = desc->hdr; desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT ; - desc2->hdr1 = desc2->hdr; desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD ; desc->hdr |=DESC_HDR_MODE0_MDEU_CONT ; desc->hdr &= ~DESC_HDR_DONE_NOTIFY ;
@@ -1925,21 +1989,21 @@ static int common_nonsnoop_hash(struct t req_ctx->hw_context_size, req_ctx->hw_context, DMA_FROM_DEVICE); - - next_desc =dma_map_single (dev, &desc2->hdr1,TALITOS_DESC_SIZE , -DMA_BIDIRECTIONAL ); - desc->next_desc =cpu_to_be32 (next_desc); }if (sync_needed)dma_sync_single_for_device (dev, edesc->dma_link_tbl, edesc->dma_len,DMA_BIDIRECTIONAL ); - ret =talitos_submit (dev, ctx->ch, desc, callback, areq); -if (ret != -EINPROGRESS ) { -common_nonsnoop_hash_unmap (dev, edesc, areq); -kfree (edesc); - } + ret =talitos_submit (dev, ctx->ch, desc, callback, + areq); +if (ret != -EINPROGRESS ) + goto err; + +return -EINPROGRESS ; +err: +common_nonsnoop_hash_unmap (dev, edesc, areq); +kfree (edesc);return ret; }
drivers/crypto/talitos.h +2 -0
@@ -49,6 +49,7 @@ struct talitos_desc {* @iv_dma: dma address of iv for checking continuity and link table * @dma_len: length of dma mapped link_tbl space * @dma_link_tbl: bus physical address of link_tbl/buf +* @next_desc: next descriptor * @desc: h/w descriptor * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2) * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
@@ -63,6 +64,7 @@ struct talitos_edesc {dma_addr_t iv_dma;int dma_len;dma_addr_t dma_link_tbl; +struct talitos_edesc *next_desc;struct talitos_desc desc;union { DECLARE_FLEX_ARRAY(struct talitos_ptr, link_tbl);
Greg Kroah-Hartman
maintainerPATCH 280/1266 crypto: talitos - move dma unmapping code in flush_channel() into a standalone dma_unmap_request() function
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit 4d9b0b7415b9e79a3d54d18b5ff230974ea78740 upstream.
Previously added code to flush_channel() in order to unmap an entire descriptor.
Move that code into a standalone function to improve readability.
--- drivers/crypto/talitos.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-)
drivers/crypto/talitos.c +22 -17
@@ -372,6 +372,27 @@ static __be32 get_request_hdr(struct devreturn edesc->desc.hdr1; } +static void dma_unmap_request (struct device *dev, +struct talitos_request *request,bool is_sec1) +{ +struct talitos_edesc *edesc; + +if (is_sec1) { +dma_unmap_single (dev, request->dma_desc,TALITOS_DESC_SIZE , +DMA_BIDIRECTIONAL ); + edesc = container_of(request->desc, struct talitos_edesc, desc); +while (edesc->next_desc) { +dma_unmap_single (dev, +be32_to_cpu (edesc->desc.next_desc), +TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); + edesc = edesc->next_desc; + } + }else { +dma_unmap_single (dev, request->dma_desc,TALITOS_DESC_SIZE , +DMA_BIDIRECTIONAL ); + } +} +/* * process what was done, notify callback of error if not */
@@ -379,7 +400,6 @@ static void flush_channel(struct device {struct talitos_private *priv =dev_get_drvdata (dev);struct talitos_request *request, saved_req; -struct talitos_edesc *edesc;unsigned long flags;int tail, status;bool is_sec1 =has_ftr_sec1 (priv);
@@ -404,22 +424,7 @@ static void flush_channel(struct deviceelse status = error; -if (is_sec1) { -dma_unmap_single (dev, request->dma_desc, -TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); - edesc =container_of (request->desc, - struct talitos_edesc, desc); -while (edesc->next_desc) { -dma_unmap_single ( - dev,be32_to_cpu (edesc->desc.next_desc), -TALITOS_DESC_SIZE ,DMA_BIDIRECTIONAL ); - edesc = edesc->next_desc; - } - }else { -dma_unmap_single (dev, request->dma_desc, -TALITOS_DESC_SIZE , -DMA_BIDIRECTIONAL ); - } +dma_unmap_request (dev, request, is_sec1);/* copy entries so we can call callback outside lock */ saved_req.desc = request->desc;
Greg Kroah-Hartman
maintainerPATCH 281/1266 crypto: talitos - move dma mapping code in talitos_submit() into a standalone dma_map_request() function
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit 5c0aa8cad7745505297103f05dda3fa06e8ac670 upstream.
Previously added code to talitos_submit() in order to map an entire descriptor chain.
Move that code into a standalone function to improve readability.
--- drivers/crypto/talitos.c | 75 +++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 34 deletions(-)
drivers/crypto/talitos.c +41 -34
@@ -255,6 +255,46 @@ static int init_device(struct device *dereturn 0 ; } +static void dma_map_request (struct device *dev,struct talitos_request *request, +struct talitos_desc *desc,bool is_sec1) +{ +struct talitos_edesc *edesc = + container_of(desc, struct talitos_edesc, desc); +dma_addr_t dma_desc, prev_dma_desc; +struct talitos_edesc *prev_edesc =NULL ; + +if (is_sec1) { +while (edesc) { + edesc->desc.hdr1 = edesc->desc.hdr; + + dma_desc =dma_map_single (dev, &edesc->desc.hdr1, +TALITOS_DESC_SIZE , +DMA_BIDIRECTIONAL ); + +if (!prev_edesc) { + request->dma_desc = dma_desc; + goto next; + } + +/* Chain in any previous descriptors. */ + + prev_edesc->desc.next_desc =cpu_to_be32 (dma_desc); + +dma_sync_single_for_device (dev, prev_dma_desc, +TALITOS_DESC_SIZE , +DMA_TO_DEVICE ); + +next: + prev_edesc = edesc; + prev_dma_desc = dma_desc; + edesc = edesc->next_desc; + } + }else { + request->dma_desc =dma_map_single (dev, desc,TALITOS_DESC_SIZE , +DMA_BIDIRECTIONAL ); + } +} +/** * talitos_submit - submits a descriptor to the device for processing * @dev: the SEC device to be used
@@ -273,10 +313,7 @@ static int talitos_submit(struct device void *context, int error), void *context) { - struct talitos_edesc *edesc = container_of(desc, struct talitos_edesc, desc); struct talitos_private *priv = dev_get_drvdata(dev); -dma_addr_t dma_desc, prev_dma_desc; -struct talitos_edesc *prev_edesc =NULL ;struct talitos_request *request;unsigned long flags;int head;
@@ -294,37 +331,7 @@ static int talitos_submit(struct device request = &priv->chan[ch].fifo[head];/* map descriptor and save caller data */ -if (is_sec1) { -while (edesc) { - edesc->desc.hdr1 = edesc->desc.hdr; - - dma_desc =dma_map_single (dev, &edesc->desc.hdr1, -TALITOS_DESC_SIZE , -DMA_BIDIRECTIONAL ); - -if (!prev_edesc) { - request->dma_desc = dma_desc; - goto next; - } - -/* Chain in any previous descriptors. */ - - prev_edesc->desc.next_desc =cpu_to_be32 (dma_desc); - -dma_sync_single_for_device (dev, prev_dma_desc, -TALITOS_DESC_SIZE , -DMA_TO_DEVICE ); - -next: - prev_edesc = edesc; - prev_dma_desc = dma_desc; - edesc = edesc->next_desc; - } - }else { - request->dma_desc =dma_map_single (dev, desc, -TALITOS_DESC_SIZE , -DMA_BIDIRECTIONAL ); - } +dma_map_request (dev, request, desc, is_sec1); request->callback = callback; request->context = context;
Greg Kroah-Hartman
maintainerPATCH 282/1266 crypto: talitos - move code in current_desc_hdr() into a standalone function
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit f8713d9e6091755dd30f7f1cfa25f8440cddf81b upstream.
Previously added code in current_desc_hdr() in order to add support for searching an offending descriptor inside a descriptor chain.
Move that code into a standalone function to improve readability.
--- drivers/crypto/talitos.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-)
drivers/crypto/talitos.c +19 -16
@@ -520,6 +520,24 @@ DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0 DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE) DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE) +static __be32 search_desc_hdr_in_request (struct talitos_request *request, +dma_addr_t cur_desc,bool is_sec1) +{ +struct talitos_edesc *edesc; + +if (request->dma_desc == cur_desc) { +return request->desc->hdr; + }else if (is_sec1) { + edesc = container_of(request->desc, struct talitos_edesc, desc); +while (edesc->next_desc) { +if (edesc->desc.next_desc ==cpu_to_be32 (cur_desc)) +return edesc->next_desc->desc.hdr1; + edesc = edesc->next_desc; + } + } +return 0 ; +} +/* * locate current (offending) descriptor */
@@ -528,7 +546,6 @@ static __be32 current_desc_hdr(struct destruct talitos_private *priv =dev_get_drvdata (dev);bool is_sec1 =has_ftr_sec1 (priv);struct talitos_request *request; -struct talitos_edesc *edesc;int tail, iter;dma_addr_t cur_desc;__be32 hdr =0 ;
@@ -546,21 +563,7 @@ static __be32 current_desc_hdr(struct de do { request = &priv->chan[ch].fifo[iter]; - if (request->dma_desc == cur_desc) { - hdr = request->desc->hdr; - } else if (is_sec1) { - edesc = container_of(request->desc, - struct talitos_edesc, desc); - while (edesc->next_desc) { - if (edesc->desc.next_desc == - cpu_to_be32(cur_desc)) { - hdr = edesc->next_desc->desc.hdr1; - break; - } - edesc = edesc->next_desc; - } - } - + hdr = search_desc_hdr_in_request(request, cur_desc, is_sec1); if (hdr) break;
Greg Kroah-Hartman
maintainerPATCH 283/1266 crypto: talitos/hash - prepare SEC1 descriptor chaining, remove additional descriptor
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit 59b5d899e33701665f18abe6bebf987427876e3e upstream.
Currently, when SEC1 has buffered data (nbuf != 0), the ahash code creates an additional descriptor on the fly inside common_nonsnoop_hash() to handle the remainder of the data. This approach is incompatible with the arbitrary-length descriptor chaining that follows.
Remove the "additional descriptor" logic from common_nonsnoop_hash() and common_nonsnoop_hash_unmap().
Also remove the nbytes adjustment for SEC1 in ahash_edesc_alloc() that subtracted nbuf.
--- drivers/crypto/talitos.c | 101 ++--------------------------------------------- 1 file changed, 6 insertions(+), 95 deletions(-)
drivers/crypto/talitos.c +6 -95
@@ -1788,15 +1788,9 @@ static void common_nonsnoop_hash_unmap(sstruct talitos_private *priv =dev_get_drvdata (dev);bool is_sec1 =has_ftr_sec1 (priv);struct talitos_desc *desc = &edesc->desc; -struct talitos_desc *desc2; - -if (desc->next_desc) - desc2 = &edesc->next_desc->desc;unmap_single_talitos_ptr (dev, &desc->ptr[5 ],DMA_FROM_DEVICE ); -if (desc->next_desc && - desc->ptr[5 ].ptr != desc2->ptr[5 ].ptr) -unmap_single_talitos_ptr (dev, &desc2->ptr[5 ],DMA_FROM_DEVICE ); +if (req_ctx->last_desc)memcpy (areq->result, req_ctx->hw_context,crypto_ahash_digestsize (tfm));
@@ -1808,13 +1802,6 @@ static void common_nonsnoop_hash_unmap(sif (from_talitos_ptr_len (&desc->ptr[1 ], is_sec1))unmap_single_talitos_ptr (dev, &desc->ptr[1 ],DMA_TO_DEVICE ); -else if (desc->next_desc) -unmap_single_talitos_ptr (dev, &desc2->ptr[1 ], -DMA_TO_DEVICE ); - -if (is_sec1 && req_ctx->nbuf) -unmap_single_talitos_ptr (dev, &desc->ptr[3 ], -DMA_TO_DEVICE );if (edesc->dma_len) dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
@@ -1922,9 +1909,6 @@ static int common_nonsnoop_hash(struct tto_talitos_ptr (&desc->ptr[2 ], ctx->dma_key, ctx->keylen, is_sec1); -if (is_sec1 && req_ctx->nbuf) - length -= req_ctx->nbuf; - sg_count = edesc->src_nents ?:1 ;if (is_sec1 && sg_count >1 )sg_copy_to_buffer (req_ctx->psrc, sg_count, edesc->buf, length);
@@ -1934,16 +1918,10 @@ static int common_nonsnoop_hash(struct t/* * data in */ -if (is_sec1 && req_ctx->nbuf) { -map_single_talitos_ptr (dev, &desc->ptr[3 ], req_ctx->nbuf, - req_ctx->buf[req_ctx->buf_idx], -DMA_TO_DEVICE ); - }else { - sg_count =talitos_sg_map (dev, req_ctx->psrc, length, edesc, - &desc->ptr[3 ], sg_count,0 ,0 ); -if (sg_count >1 ) - sync_needed = true; - } + sg_count =talitos_sg_map (dev, req_ctx->psrc, length, edesc, + &desc->ptr[3 ], sg_count,0 ,0 ); +if (sg_count >1 ) + sync_needed = true;/* fifth DWORD empty */
@@ -1963,49 +1941,6 @@ static int common_nonsnoop_hash(struct tif (is_sec1 &&from_talitos_ptr_len (&desc->ptr[3 ], true) ==0 )talitos_handle_buggy_hash (ctx, edesc, &desc->ptr[3 ]); -if (is_sec1 && req_ctx->nbuf && length) { -struct talitos_edesc *edesc2; -struct talitos_desc *desc2; - - edesc2 =kzalloc (sizeof (*edesc2), - areq->base.flags &CRYPTO_TFM_REQ_MAY_SLEEP ? -GFP_KERNEL : -GFP_ATOMIC ); -if (!edesc2) { - ret = -ENOMEM ; - goto err; - } - edesc->next_desc = edesc2; - - desc2 = &edesc2->desc; - - desc2->hdr = desc->hdr; - desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT ; - desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD ; - desc->hdr |=DESC_HDR_MODE0_MDEU_CONT ; - desc->hdr &= ~DESC_HDR_DONE_NOTIFY ; - -if (desc->ptr[1 ].ptr) -copy_talitos_ptr (&desc2->ptr[1 ], &desc->ptr[1 ], - is_sec1); -else -map_single_talitos_ptr_nosync (dev, &desc2->ptr[1 ], - req_ctx->hw_context_size, - req_ctx->hw_context, -DMA_TO_DEVICE ); -copy_talitos_ptr (&desc2->ptr[2 ], &desc->ptr[2 ], is_sec1); - sg_count =talitos_sg_map (dev, req_ctx->psrc, length, edesc, - &desc2->ptr[3 ], sg_count,0 ,0 ); -if (sg_count >1 ) - sync_needed = true; -copy_talitos_ptr (&desc2->ptr[5 ], &desc->ptr[5 ], is_sec1); -if (req_ctx->last_desc) -map_single_talitos_ptr_nosync (dev, &desc->ptr[5 ], - req_ctx->hw_context_size, - req_ctx->hw_context, -DMA_FROM_DEVICE ); - } -if (sync_needed)dma_sync_single_for_device (dev, edesc->dma_link_tbl, edesc->dma_len,DMA_BIDIRECTIONAL );
@@ -2028,11 +1963,6 @@ static struct talitos_edesc *ahash_edescstruct crypto_ahash *tfm =crypto_ahash_reqtfm (areq);struct talitos_ctx *ctx =crypto_ahash_ctx (tfm);struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq); -struct talitos_private *priv =dev_get_drvdata (ctx->dev); -bool is_sec1 =has_ftr_sec1 (priv); - -if (is_sec1) - nbytes -= req_ctx->nbuf;return talitos_edesc_alloc (ctx->dev, req_ctx->psrc,NULL ,NULL ,0 , nbytes,0 ,0 ,0 , areq->base.flags, false);
@@ -2051,8 +1981,6 @@ static int ahash_process_req_one(structunsigned int nsg;int nents;struct device *dev = ctx->dev; -struct talitos_private *priv =dev_get_drvdata (dev); -bool is_sec1 =has_ftr_sec1 (priv);u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];if (!req_ctx->last_desc && (nbytes + req_ctx->nbuf <= blocksize)) {
@@ -2084,30 +2012,13 @@ static int ahash_process_req_one(struct }/* Chain in any previously buffered data */ -if (!is_sec1 && req_ctx->nbuf) { +if (req_ctx->nbuf) { nsg = (req_ctx->nbuf < nbytes_to_hash) ?2 :1 ;sg_init_table (req_ctx->bufsl, nsg);sg_set_buf (req_ctx->bufsl, ctx_buf, req_ctx->nbuf);if (nsg >1 )sg_chain (req_ctx->bufsl,2 , req_ctx->request_sl); req_ctx->psrc = req_ctx->bufsl; - }else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) { -int offset; - -if (nbytes_to_hash > blocksize) - offset = blocksize - req_ctx->nbuf; -else - offset = nbytes_to_hash - req_ctx->nbuf; - nents =sg_nents_for_len (req_ctx->request_sl, offset); -if (nents <0 ) { -dev_err (dev,"Invalid number of src SG.\n" ); -return nents; - } -sg_copy_to_buffer (req_ctx->request_sl, nents, - ctx_buf + req_ctx->nbuf, offset); - req_ctx->nbuf += offset; - req_ctx->psrc =scatterwalk_ffwd (req_ctx->bufsl, req_ctx->request_sl, - offset); }else req_ctx->psrc = req_ctx->request_sl;
Greg Kroah-Hartman
maintainerPATCH 284/1266 crypto: talitos/hash - use descriptor chaining for SEC1 instead of workqueue
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit f1ede6d95d8ad3b32c6a552d2baab805bd00fc38 upstream.
Rework the SEC1 ahash implementation to build a chain of hardware descriptors, replacing the previous approach of submitting one descriptor at a time via a workqueue, introduced by commit 655ef638a2bc ("crypto: talitos - fix SEC1 32k ahash request limitation").
Introduce ahash_process_req_prepare() which iterates over the request data, allocating enough descriptors to cover the entire ahash request. The new fields (bufsl, src, first, last) are added to talitos_edesc for this purpose.
common_nonsnoop_hash() no longer calls talitos_submit(); it only maps and sets up the descriptor. Submission is now done by the caller after the chain is built.
ahash_free_desc_list_from() takes over calling common_nonsnoop_hash_unmap() for each descriptor during cleanup.
Compared to the workqueue based solution, request are slightly faster since there is no more scheduling latency induced by the workqueue, and only one interrupt is generated by the device at the end of a chain.
Commit 655ef638a2bc ("crypto: talitos - fix SEC1 32k ahash request limitation") :
$ /usr/libexec/libkcapi/sha256sum ./test_5M.bin 013c5609d63c... ./test_5M.bin real 0m 0.41s user 0m 0.01s sys 0m 0.07s
Now :
$ /usr/libexec/libkcapi/sha256sum ./test_5M.bin 013c5609d63c... ./test_5M.bin real 0m 0.33s user 0m 0.01s sys 0m 0.20s
Tested on a system with an MPC885 SoC featuring the SEC1 Lite.
The increase in sys time is due to the fact that commit 37b5e8897eb5 ("crypto: talitos - chain in buffered data for ahash on SEC1") can no longer be applied.
--- drivers/crypto/talitos.c | 168 +++++++++++++++++++++++++++++------------------ drivers/crypto/talitos.h | 10 ++ 2 files changed, 115 insertions(+), 63 deletions(-)
drivers/crypto/talitos.c +105 -63
@@ -1791,12 +1791,12 @@ static void common_nonsnoop_hash_unmap(sunmap_single_talitos_ptr (dev, &desc->ptr[5 ],DMA_FROM_DEVICE ); -if (req_ctx->last_desc) +if (edesc->last && req_ctx->last_request)memcpy (areq->result, req_ctx->hw_context,crypto_ahash_digestsize (tfm)); -if (req_ctx->psrc) -talitos_sg_unmap (dev, edesc, req_ctx->psrc,NULL ,0 ,0 ); +if (edesc->src) +talitos_sg_unmap (dev, edesc, edesc->src,NULL ,0 ,0 );/* When using hashctx-in, must unmap it. */ if (from_talitos_ptr_len (&desc->ptr[1 ], is_sec1))
@@ -1808,12 +1808,14 @@ static void common_nonsnoop_hash_unmap(s DMA_BIDIRECTIONAL); } -static void free_edesc_list_from (struct talitos_edesc *edesc) +static void free_edesc_list_from (struct ahash_request *areq,struct talitos_edesc *edesc) { +struct talitos_ctx *ctx =crypto_ahash_ctx (crypto_ahash_reqtfm (areq));struct talitos_edesc *next;while (edesc) { next = edesc->next_desc; +common_nonsnoop_hash_unmap (ctx->dev, edesc, areq);kfree (edesc); edesc = next; }
@@ -1828,19 +1830,18 @@ static void ahash_done(struct device *de container_of(desc, struct talitos_edesc, desc);struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq); +if (!req_ctx->last_desc && req_ctx->to_hash_later) {/* Position any partial block for next update/final/finup */ req_ctx->buf_idx = (req_ctx->buf_idx +1 ) &1 ; req_ctx->nbuf = req_ctx->to_hash_later; } -common_nonsnoop_hash_unmap (dev, edesc, areq); -free_edesc_list_from (edesc); +free_edesc_list_from (areq, edesc); -if (err) { -ahash_request_complete (areq, err); -return ; - } +ahash_request_complete (areq, err); + +return ; req_ctx->remaining_ahash_request_bytes -= req_ctx->current_ahash_request_bytes;
@@ -1874,18 +1875,15 @@ static void talitos_handle_buggy_hash(st (char *)padded_hash, DMA_TO_DEVICE); } -static int common_nonsnoop_hash (struct talitos_edesc *edesc, -struct ahash_request *areq,unsigned int length, -void (*callback) (struct device *dev, -struct talitos_desc *desc, -void *context,int error)) +static void common_nonsnoop_hash (struct talitos_edesc *edesc, +struct ahash_request *areq, +unsigned int length) {struct crypto_ahash *tfm =crypto_ahash_reqtfm (areq);struct talitos_ctx *ctx =crypto_ahash_ctx (tfm);struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq);struct device *dev = ctx->dev;struct talitos_desc *desc = &edesc->desc; -int ret;bool sync_needed = false;struct talitos_private *priv =dev_get_drvdata (dev);bool is_sec1 =has_ftr_sec1 (priv);
@@ -1894,7 +1892,7 @@ static int common_nonsnoop_hash(struct t/* first DWORD empty */ /* hash context in */ -if (!req_ctx->first_desc || req_ctx->swinit) { +if (!edesc->first || !req_ctx->first_desc || req_ctx->swinit) { map_single_talitos_ptr_nosync(dev, &desc->ptr[1], req_ctx->hw_context_size, req_ctx->hw_context,
@@ -1911,22 +1909,22 @@ static int common_nonsnoop_hash(struct t sg_count = edesc->src_nents ?:1 ;if (is_sec1 && sg_count >1 ) -sg_copy_to_buffer (req_ctx->psrc, sg_count, edesc->buf, length); +sg_copy_to_buffer (edesc->src, sg_count, edesc->buf, length);else if (length) - sg_count =dma_map_sg (dev, req_ctx->psrc, sg_count, -DMA_TO_DEVICE ); + sg_count =dma_map_sg (dev, edesc->src, sg_count,DMA_TO_DEVICE ); +/* * data in */ - sg_count =talitos_sg_map (dev, req_ctx->psrc, length, edesc, - &desc->ptr[3 ], sg_count,0 ,0 ); + sg_count =talitos_sg_map (dev, edesc->src, length, edesc, &desc->ptr[3 ], + sg_count,0 ,0 );if (sg_count >1 ) sync_needed = true;/* fifth DWORD empty */ /* hash/HMAC out -or- hash context out */ -if (req_ctx->last_desc) +if (edesc->last && req_ctx->last_request)map_single_talitos_ptr (dev, &desc->ptr[5 ],crypto_ahash_digestsize (tfm), req_ctx->hw_context,DMA_FROM_DEVICE );
@@ -1944,30 +1942,89 @@ static int common_nonsnoop_hash(struct tif (sync_needed)dma_sync_single_for_device (dev, edesc->dma_link_tbl, edesc->dma_len,DMA_BIDIRECTIONAL ); - - ret =talitos_submit (dev, ctx->ch, desc, callback, - areq); -if (ret != -EINPROGRESS ) - goto err; - -return -EINPROGRESS ; -err: -common_nonsnoop_hash_unmap (dev, edesc, areq); -kfree (edesc); -return ret; }static struct talitos_edesc *ahash_edesc_alloc (struct ahash_request *areq, +struct scatterlist *src,unsigned int nbytes) {struct crypto_ahash *tfm =crypto_ahash_reqtfm (areq);struct talitos_ctx *ctx =crypto_ahash_ctx (tfm); -struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq); -return talitos_edesc_alloc (ctx->dev, req_ctx->psrc,NULL ,NULL ,0 , +return talitos_edesc_alloc (ctx->dev, src,NULL ,NULL ,0 , nbytes,0 ,0 ,0 , areq->base.flags, false); } +static struct talitos_edesc * +ahash_process_req_prepare (struct ahash_request *areq,unsigned int nbytes, +unsigned int blocksize,bool is_sec1) +{ +struct talitos_ctx *ctx =crypto_ahash_ctx (crypto_ahash_reqtfm (areq)); +struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq); +struct talitos_edesc *first =NULL , *prev_edesc =NULL , *edesc; +size_t desc_max = is_sec1 ?TALITOS1_MAX_DATA_LEN :SIZE_MAX ; +struct scatterlist tmp[2 ]; +size_t to_hash_this_desc; +struct scatterlist *src; +size_t offset =0 ; + +do { + src =scatterwalk_ffwd (tmp, req_ctx->psrc, offset); + + to_hash_this_desc = +min (nbytes,ALIGN_DOWN (desc_max, blocksize)); + +/* Allocate extended descriptor */ + edesc =ahash_edesc_alloc (areq, src, to_hash_this_desc); +if (IS_ERR (edesc)) { +if (first) +free_edesc_list_from (areq, first); +return edesc; + } + + edesc->src = +scatterwalk_ffwd (edesc->bufsl, req_ctx->psrc, offset); + edesc->desc.hdr = ctx->desc_hdr_template; + edesc->first = offset ==0 ; + edesc->last = nbytes - to_hash_this_desc ==0 ; + +/* On last one, request SEC to pad; otherwise continue */ +if (req_ctx->last_request && edesc->last) + edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_PAD ; +else + edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_CONT ; + +/* request SEC to INIT hash. */ +if (req_ctx->first_desc && edesc->first && !req_ctx->swinit) + edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_INIT ; + +/* +* When the tfm context has a keylen, it's an HMAC. +* A first or last (ie. not middle) descriptor must request HMAC. +*/ +if (ctx->keylen && ((req_ctx->first_desc && edesc->first) || + (req_ctx->last_request && edesc->last))) + edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_HMAC ; + +/* clear the DN bit */ +if (is_sec1 && !edesc->last) + edesc->desc.hdr &= ~DESC_HDR_DONE_NOTIFY ; + +common_nonsnoop_hash (edesc, areq, to_hash_this_desc); + + offset += to_hash_this_desc; + nbytes -= to_hash_this_desc; + +if (!prev_edesc) + first = edesc; +else + prev_edesc->next_desc = edesc; + prev_edesc = edesc; + }while (nbytes); + +return first; +} +static int ahash_process_req_one (struct ahash_request *areq,unsigned int nbytes) {struct crypto_ahash *tfm =crypto_ahash_reqtfm (areq);
@@ -1976,14 +2033,16 @@ static int ahash_process_req_one(structstruct talitos_edesc *edesc;unsigned int blocksize =crypto_tfm_alg_blocksize (crypto_ahash_tfm (tfm)); +bool is_sec1 =has_ftr_sec1 (dev_get_drvdata (ctx->dev));unsigned int nbytes_to_hash;unsigned int to_hash_later;unsigned int nsg;int nents;struct device *dev = ctx->dev;u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx]; +int ret; -if (!req_ctx->last_desc && (nbytes + req_ctx->nbuf <= blocksize)) { +if (!req_ctx->last_request && (nbytes + req_ctx->nbuf <= blocksize)) {/* Buffer up to one whole block */ nents =sg_nents_for_len (req_ctx->request_sl, nbytes);if (nents <0 ) {
@@ -2000,7 +2059,7 @@ static int ahash_process_req_one(struct nbytes_to_hash = nbytes + req_ctx->nbuf; to_hash_later = nbytes_to_hash & (blocksize -1 ); -if (req_ctx->last_desc) +if (req_ctx->last_request) to_hash_later =0 ;else if (to_hash_later)/* There is a partial block. Hash the full block(s) now */
@@ -2035,30 +2094,16 @@ static int ahash_process_req_one(struct } req_ctx->to_hash_later = to_hash_later; -/* Allocate extended descriptor */ - edesc =ahash_edesc_alloc (req_ctx->areq, nbytes_to_hash); + edesc =ahash_process_req_prepare (areq, nbytes_to_hash, blocksize, + is_sec1);if (IS_ERR (edesc))return PTR_ERR (edesc); - edesc->desc.hdr = ctx->desc_hdr_template; - -/* On last one, request SEC to pad; otherwise continue */ -if (req_ctx->last_desc) - edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_PAD ; -else - edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_CONT ; - -/* request SEC to INIT hash. */ -if (req_ctx->first_desc && !req_ctx->swinit) - edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_INIT ; - -/* When the tfm context has a keylen, it's an HMAC. -* A first or last (ie. not middle) descriptor must request HMAC. -*/ -if (ctx->keylen && (req_ctx->first_desc || req_ctx->last_desc)) - edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_HMAC ; + ret =talitos_submit (dev, ctx->ch, &edesc->desc, ahash_done, areq); +if (ret != -EINPROGRESS ) +free_edesc_list_from (areq, edesc); -return common_nonsnoop_hash (edesc, req_ctx->areq, nbytes_to_hash, ahash_done); +return ret; }static void sec1_ahash_process_remaining (struct work_struct *work)
@@ -2102,16 +2147,13 @@ static int ahash_process_req(struct ahas req_ctx->remaining_ahash_request_bytes = nbytes;if (is_sec1) { -if (nbytes >TALITOS1_MAX_DATA_LEN ) - nbytes =TALITOS1_MAX_DATA_LEN ; -else if (req_ctx->last_request) +if (req_ctx->last_request) req_ctx->last_desc =1 ; } req_ctx->current_ahash_request_bytes = nbytes; -return ahash_process_req_one (req_ctx->areq, - req_ctx->current_ahash_request_bytes); +return ahash_process_req_one (req_ctx->areq, nbytes); }static int ahash_init (struct ahash_request *areq)
drivers/crypto/talitos.h +10 -0
@@ -44,6 +44,11 @@ struct talitos_desc {/* * talitos_edesc - s/w-extended descriptor +* @bufsl: scatterlist buffer +* @src: pointer to input scatterlist +* @first: first descriptor of a chain +* @last: last descriptor of a chain +* * @src_nents: number of segments in input scatterlist * @dst_nents: number of segments in output scatterlist * @iv_dma: dma address of iv for checking continuity and link table
@@ -59,6 +64,11 @@ struct talitos_desc {* of link_tbl data */ struct talitos_edesc { +struct scatterlist bufsl[2 ]; +struct scatterlist *src; +int first; +int last; +int src_nents;int dst_nents;dma_addr_t iv_dma;
Greg Kroah-Hartman
maintainerPATCH 285/1266 crypto: talitos/hash - drop workqueue mechanism for SEC1
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit be4802afb1700534e48cb776d0d1e772c27de130 upstream.
Now that SEC1 hash uses hardware descriptor chaining instead of a workqueue to process requests exceeding TALITOS1_MAX_DATA_LEN, the workqueue code is no longer needed.
Remove sec1_ahash_process_remaining(), the related fields from talitos_ahash_req_ctx (request_bufsl, areq, request_sl, remaining_ahash_request_bytes, current_ahash_request_bytes, sec1_ahash_process_remaining), the dead code in ahash_done(), and simplify ahash_process_req() to call ahash_process_req_one() directly with the original areq->src and areq->nbytes.
--- drivers/crypto/talitos.c | 80 ++++------------------------------------------- 1 file changed, 7 insertions(+), 73 deletions(-)
drivers/crypto/talitos.c +7 -73
@@ -12,7 +12,6 @@* All rights reserved. */ -#include <linux/workqueue.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mod_devicetable.h>
@@ -952,13 +951,6 @@ struct talitos_ahash_req_ctx {unsigned int nbuf;struct scatterlist bufsl[2 ];struct scatterlist *psrc; - -struct scatterlist request_bufsl[2 ]; -struct ahash_request *areq; -struct scatterlist *request_sl; -unsigned int remaining_ahash_request_bytes; -unsigned int current_ahash_request_bytes; -struct work_struct sec1_ahash_process_remaining; };struct talitos_export_state {
@@ -1840,18 +1832,6 @@ static void ahash_done(struct device *defree_edesc_list_from (areq, edesc);ahash_request_complete (areq, err); - -return ; - - req_ctx->remaining_ahash_request_bytes -= - req_ctx->current_ahash_request_bytes; - -if (!req_ctx->remaining_ahash_request_bytes) { -ahash_request_complete (areq,0 ); -return ; - } - -schedule_work (&req_ctx->sec1_ahash_process_remaining); }/*
@@ -2044,12 +2024,12 @@ static int ahash_process_req_one(structif (!req_ctx->last_request && (nbytes + req_ctx->nbuf <= blocksize)) {/* Buffer up to one whole block */ - nents =sg_nents_for_len (req_ctx->request_sl, nbytes); + nents =sg_nents_for_len (areq->src, nbytes);if (nents <0 ) {dev_err (dev,"Invalid number of src SG.\n" );return nents; } -sg_copy_to_buffer (req_ctx->request_sl, nents, +sg_copy_to_buffer (areq->src, nents, ctx_buf + req_ctx->nbuf, nbytes); req_ctx->nbuf += nbytes;return 0 ;
@@ -2076,18 +2056,18 @@ static int ahash_process_req_one(structsg_init_table (req_ctx->bufsl, nsg);sg_set_buf (req_ctx->bufsl, ctx_buf, req_ctx->nbuf);if (nsg >1 ) -sg_chain (req_ctx->bufsl,2 , req_ctx->request_sl); +sg_chain (req_ctx->bufsl,2 , areq->src); req_ctx->psrc = req_ctx->bufsl; }else - req_ctx->psrc = req_ctx->request_sl; + req_ctx->psrc = areq->src;if (to_hash_later) { - nents =sg_nents_for_len (req_ctx->request_sl, nbytes); + nents =sg_nents_for_len (areq->src, nbytes);if (nents <0 ) {dev_err (dev,"Invalid number of src SG.\n" );return nents; } -sg_pcopy_to_buffer (req_ctx->request_sl, nents, +sg_pcopy_to_buffer (areq->src, nents, req_ctx->buf[(req_ctx->buf_idx +1 ) &1 ], to_hash_later, nbytes - to_hash_later);
@@ -2106,54 +2086,9 @@ static int ahash_process_req_one(structreturn ret; } -static void sec1_ahash_process_remaining (struct work_struct *work) -{ -struct talitos_ahash_req_ctx *req_ctx = - container_of(work, struct talitos_ahash_req_ctx, - sec1_ahash_process_remaining); -int err =0 ; - - req_ctx->request_sl =scatterwalk_ffwd (req_ctx->request_bufsl, - req_ctx->request_sl,TALITOS1_MAX_DATA_LEN ); - -if (req_ctx->remaining_ahash_request_bytes >TALITOS1_MAX_DATA_LEN ) - req_ctx->current_ahash_request_bytes =TALITOS1_MAX_DATA_LEN ; -else { - req_ctx->current_ahash_request_bytes = - req_ctx->remaining_ahash_request_bytes; - -if (req_ctx->last_request) - req_ctx->last_desc =1 ; - } - - err =ahash_process_req_one (req_ctx->areq, - req_ctx->current_ahash_request_bytes); - -if (err != -EINPROGRESS ) -ahash_request_complete (req_ctx->areq, err); -} -static int ahash_process_req (struct ahash_request *areq,unsigned int nbytes) { -struct crypto_ahash *tfm =crypto_ahash_reqtfm (areq); -struct talitos_ctx *ctx =crypto_ahash_ctx (tfm); -struct device *dev = ctx->dev; -struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq); -struct talitos_private *priv =dev_get_drvdata (dev); -bool is_sec1 =has_ftr_sec1 (priv); - - req_ctx->areq = areq; - req_ctx->request_sl = areq->src; - req_ctx->remaining_ahash_request_bytes = nbytes; - -if (is_sec1) { -if (req_ctx->last_request) - req_ctx->last_desc =1 ; - } - - req_ctx->current_ahash_request_bytes = nbytes; - -return ahash_process_req_one (req_ctx->areq, nbytes); +return ahash_process_req_one (areq, nbytes); }static int ahash_init (struct ahash_request *areq)
@@ -2176,7 +2111,6 @@ static int ahash_init(struct ahash_reque req_ctx->hw_context_size = size; req_ctx->last_request =0 ; req_ctx->last_desc =0 ; -INIT_WORK (&req_ctx->sec1_ahash_process_remaining, sec1_ahash_process_remaining); dma =dma_map_single (dev, req_ctx->hw_context, req_ctx->hw_context_size,DMA_TO_DEVICE );
Greg Kroah-Hartman
maintainerPATCH 286/1266 crypto: talitos/hash - rename first_desc/last_desc to first_request/last_request
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit 8bcf00671400ac3b3a4cc3011e6c1496dbd880fd upstream.
In talitos_ahash_req_ctx and talitos_export_state, the fields first_desc and last_desc describe request-level (not descriptor-level) state. Rename them to first_request and last_request for clarity. last_desc is also removed from talitos_ahash_req_ctx as it is no longer used.
--- drivers/crypto/talitos.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-)
drivers/crypto/talitos.c +13 -16
@@ -944,8 +944,7 @@ struct talitos_ahash_req_ctx {u8 buf[2 ][HASH_MAX_BLOCK_SIZE ];int buf_idx;unsigned int swinit; -unsigned int first_desc; -unsigned int last_desc; +unsigned int first_request;unsigned int last_request;unsigned int to_hash_later;unsigned int nbuf;
@@ -957,8 +956,8 @@ struct talitos_export_state {u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE /sizeof (u32)];u8 buf[HASH_MAX_BLOCK_SIZE ];unsigned int swinit; -unsigned int first_desc; -unsigned int last_desc; +unsigned int first_request; +unsigned int last_request;unsigned int to_hash_later;unsigned int nbuf; };
@@ -1822,8 +1821,7 @@ static void ahash_done(struct device *de container_of(desc, struct talitos_edesc, desc);struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq); - -if (!req_ctx->last_desc && req_ctx->to_hash_later) { +if (!req_ctx->last_request && req_ctx->to_hash_later) {/* Position any partial block for next update/final/finup */ req_ctx->buf_idx = (req_ctx->buf_idx +1 ) &1 ; req_ctx->nbuf = req_ctx->to_hash_later;
@@ -1872,7 +1870,7 @@ static void common_nonsnoop_hash(struct/* first DWORD empty */ /* hash context in */ -if (!edesc->first || !req_ctx->first_desc || req_ctx->swinit) { +if (!edesc->first || !req_ctx->first_request || req_ctx->swinit) { map_single_talitos_ptr_nosync(dev, &desc->ptr[1], req_ctx->hw_context_size, req_ctx->hw_context,
@@ -1880,7 +1878,7 @@ static void common_nonsnoop_hash(struct req_ctx->swinit =0 ; }/* Indicate next op is not the first. */ - req_ctx->first_desc =0 ; + req_ctx->first_request =0 ;/* HMAC key */ if (ctx->keylen)
@@ -1975,14 +1973,14 @@ ahash_process_req_prepare(struct ahash_r edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_CONT ;/* request SEC to INIT hash. */ -if (req_ctx->first_desc && edesc->first && !req_ctx->swinit) +if (req_ctx->first_request && edesc->first && !req_ctx->swinit) edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_INIT ;/* * When the tfm context has a keylen, it's an HMAC. * A first or last (ie. not middle) descriptor must request HMAC. */ -if (ctx->keylen && ((req_ctx->first_desc && edesc->first) || +if (ctx->keylen && ((req_ctx->first_request && edesc->first) || (req_ctx->last_request && edesc->last))) edesc->desc.hdr |=DESC_HDR_MODE0_MDEU_HMAC ;
@@ -2103,14 +2101,13 @@ static int ahash_init(struct ahash_reque/* Initialize the context */ req_ctx->buf_idx =0 ; req_ctx->nbuf =0 ; - req_ctx->first_desc =1 ;/* first_desc indicates h/w must init its context */ + req_ctx->first_request =1 ; req_ctx->swinit =0 ;/* assume h/w init of context */ size = (crypto_ahash_digestsize (tfm) <=SHA256_DIGEST_SIZE ) ?TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 :TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512 ; req_ctx->hw_context_size = size; req_ctx->last_request =0 ; - req_ctx->last_desc =0 ; dma =dma_map_single (dev, req_ctx->hw_context, req_ctx->hw_context_size,DMA_TO_DEVICE );
@@ -2202,8 +2199,8 @@ static int ahash_export(struct ahash_req req_ctx->hw_context_size);memcpy (export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf); export->swinit = req_ctx->swinit; - export->first_desc = req_ctx->first_desc; - export->last_desc = req_ctx->last_desc; + export->first_request = req_ctx->first_request; + export->last_request = req_ctx->last_request; export->to_hash_later = req_ctx->to_hash_later; export->nbuf = req_ctx->nbuf;
@@ -2228,8 +2225,8 @@ static int ahash_import(struct ahash_reqmemcpy (req_ctx->hw_context, export->hw_context, size);memcpy (req_ctx->buf[0 ], export->buf, export->nbuf); req_ctx->swinit = export->swinit; - req_ctx->first_desc = export->first_desc; - req_ctx->last_desc = export->last_desc; + req_ctx->first_request = export->first_request; + req_ctx->last_request = export->last_request; req_ctx->to_hash_later = export->to_hash_later; req_ctx->nbuf = export->nbuf;
Greg Kroah-Hartman
maintainerPATCH 287/1266 crypto: talitos/hash - remove useless wrapper
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit 907ae6088c82c9abae2d26477fddd60df6ad003b upstream.
ahash_process_req() was a wrapper used in commit 655ef638a2bc ("crypto:
talitos - fix SEC1 32k ahash request limitation"). Rename ahash_process_req_one() to ahash_process_req() and remove the wrapper.
--- drivers/crypto/talitos.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/crypto/talitos.c +1 -6
@@ -2003,7 +2003,7 @@ ahash_process_req_prepare(struct ahash_rreturn first; } -static int ahash_process_req_one (struct ahash_request *areq,unsigned int nbytes) +static int ahash_process_req (struct ahash_request *areq,unsigned int nbytes) {struct crypto_ahash *tfm =crypto_ahash_reqtfm (areq);struct talitos_ctx *ctx =crypto_ahash_ctx (tfm);
@@ -2084,11 +2084,6 @@ static int ahash_process_req_one(structreturn ret; } -static int ahash_process_req (struct ahash_request *areq,unsigned int nbytes) -{ -return ahash_process_req_one (areq, nbytes); -} -static int ahash_init (struct ahash_request *areq) {struct crypto_ahash *tfm =crypto_ahash_reqtfm (areq);
Greg Kroah-Hartman
maintainerPATCH 288/1266 crypto: talitos/hash - fix SEC2 64k - 1 ahash request limitation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Louvel <[email protected]>
commit 6e12daff6ec125102a6fdcafc5aa7199f7ce8933 upstream.
The problem described in commit 655ef638a2bc ("crypto: talitos - fix SEC1 32k ahash request limitation") also apply for the SEC2 hardware, but with a limitation of 64k - 1 bytes.
Split ahash_done() into SEC1 and SEC2 paths: SEC1 continues to free the whole descriptor list at once, while SEC2 now iterates through descriptors one by one, submitting the next only after the previous completes, which is required since SEC2 cannot chain descriptors in hardware.
--- drivers/crypto/talitos.c | 49 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-)
drivers/crypto/talitos.c +40 -9
@@ -1820,16 +1820,46 @@ static void ahash_done(struct device *destruct talitos_edesc *edesc = container_of(desc, struct talitos_edesc, desc);struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq); +struct crypto_ahash *tfm =crypto_ahash_reqtfm (areq); +bool is_sec1 =has_ftr_sec1 (dev_get_drvdata (dev)); +struct talitos_ctx *ctx =crypto_ahash_ctx (tfm); +struct talitos_edesc *next; -if (!req_ctx->last_request && req_ctx->to_hash_later) { -/* Position any partial block for next update/final/finup */ - req_ctx->buf_idx = (req_ctx->buf_idx +1 ) &1 ; - req_ctx->nbuf = req_ctx->to_hash_later; +if (is_sec1) { +if (!req_ctx->last_request && req_ctx->to_hash_later) { +/* Position any partial block for next update/final/finup */ + req_ctx->buf_idx = (req_ctx->buf_idx +1 ) &1 ; + req_ctx->nbuf = req_ctx->to_hash_later; + } + +free_edesc_list_from (areq, edesc); +ahash_request_complete (areq, err); + }else { + next = edesc->next_desc; + +common_nonsnoop_hash_unmap (dev, edesc, areq); +kfree (edesc); + +if (err) + goto out; + +if (next) { + err =talitos_submit (dev, ctx->ch, &next->desc, + ahash_done, areq); +if (err != -EINPROGRESS ) + goto out; +return ; + } +out: +if (!req_ctx->last_request && req_ctx->to_hash_later) { +/* Position any partial block for next update/final/finup */ + req_ctx->buf_idx = (req_ctx->buf_idx +1 ) &1 ; + req_ctx->nbuf = req_ctx->to_hash_later; + } +if (err && next) +free_edesc_list_from (areq, next); +ahash_request_complete (areq, err); } - -free_edesc_list_from (areq, edesc); - -ahash_request_complete (areq, err); }/*
@@ -1940,7 +1970,8 @@ ahash_process_req_prepare(struct ahash_rstruct talitos_ctx *ctx =crypto_ahash_ctx (crypto_ahash_reqtfm (areq));struct talitos_ahash_req_ctx *req_ctx =ahash_request_ctx (areq);struct talitos_edesc *first =NULL , *prev_edesc =NULL , *edesc; -size_t desc_max = is_sec1 ?TALITOS1_MAX_DATA_LEN :SIZE_MAX ; +size_t desc_max = is_sec1 ?TALITOS1_MAX_DATA_LEN : +TALITOS2_MAX_DATA_LEN ;struct scatterlist tmp[2 ];size_t to_hash_this_desc;struct scatterlist *src;
Greg Kroah-Hartman
maintainerPATCH 289/1266 arm64: fpsimd: Fix type mismatch in sme_{save,load}_state()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Rutland <[email protected]>
commit 247bd153905085c18ff9006cca1ccb96dfd18e7f upstream.
The sme_save_state() and sme_load_state() functions take a 32-bit int argument that describes whether to save/restore ZT0. Their assembly implementations consume the entire 64-bit register containing this 32-bit value, and will attempt to save/restore ZT0 if any bit of that 64-bit register is non-zero.
Per the AAPCS64 parameter passing rules, the callee is responsible for any necessary widening, and the upper 32-bits are permitted to contain arbitrary values. If the upper 32 bits are non-zero, this could result in an unexpected attempt to save/restore ZT0, and consequently could lead to unexpected traps/undefs/faults.
In practice compilers are very unlikely to generate code where the upper 32-bits would be non-zero, but they are permitted to do so.
Fix this by only consuming the low 32 bits of the register, and update comments accordingly.
--- arch/arm64/kernel/entry-fpsimd.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/kernel/entry-fpsimd.S +4 -4
@@ -103,13 +103,13 @@ SYM_FUNC_END(sme_set_vq) * Save the ZA and ZT state * * x0 - pointer to buffer for state - * x1 - number of ZT registers to save + * w1 - number of ZT registers to save */ SYM_FUNC_START(sme_save_state) _sme_rdsvl 2, 1 // x2 = VL/8 sme_save_za 0, x2, 12 // Leaves x0 pointing to the end of ZA - cbz x1, 1f + cbz w1, 1f _str_zt 0 1: ret
@@ -119,13 +119,13 @@ SYM_FUNC_END(sme_save_state) * Load the ZA and ZT state * * x0 - pointer to buffer for state - * x1 - number of ZT registers to save + * w1 - number of ZT registers to save */ SYM_FUNC_START(sme_load_state) _sme_rdsvl 2, 1 // x2 = VL/8 sme_load_za 0, x2, 12 // Leaves x0 pointing to the end of ZA - cbz x1, 1f + cbz w1, 1f _ldr_zt 0 1: ret
Greg Kroah-Hartman
maintainerPATCH 290/1266 spi: fsl-lpspi: replace dmaengine_terminate_all() with dmaengine_terminate_sync()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carlos Song <[email protected]>
commit e703ce47691b967fe9b4057fb1d062273211afa9 upstream.
dmaengine_terminate_all() has been deprecated, so replace it with dmaengine_terminate_sync().
--- drivers/spi/spi-fsl-lpspi.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/spi/spi-fsl-lpspi.c +9 -9
@@ -603,7 +603,7 @@ static int fsl_lpspi_dma_transfer(struct tx->sgl, tx->nents,DMA_MEM_TO_DEV , DMA_PREP_INTERRUPT | DMA_CTRL_ACK);if (!desc_tx) { -dmaengine_terminate_all (controller->dma_tx); +dmaengine_terminate_sync (controller->dma_tx);return -EINVAL ; }
@@ -624,8 +624,8 @@ static int fsl_lpspi_dma_transfer(struct transfer_timeout);if (!timeout) {dev_err (fsl_lpspi->dev,"I/O Error in DMA TX\n" ); -dmaengine_terminate_all (controller->dma_tx); -dmaengine_terminate_all (controller->dma_rx); +dmaengine_terminate_sync (controller->dma_tx); +dmaengine_terminate_sync (controller->dma_rx);fsl_lpspi_reset (fsl_lpspi);return -ETIMEDOUT ; }
@@ -634,8 +634,8 @@ static int fsl_lpspi_dma_transfer(struct transfer_timeout);if (!timeout) {dev_err (fsl_lpspi->dev,"I/O Error in DMA RX\n" ); -dmaengine_terminate_all (controller->dma_tx); -dmaengine_terminate_all (controller->dma_rx); +dmaengine_terminate_sync (controller->dma_tx); +dmaengine_terminate_sync (controller->dma_rx);fsl_lpspi_reset (fsl_lpspi);return -ETIMEDOUT ; }
@@ -644,8 +644,8 @@ static int fsl_lpspi_dma_transfer(struct fsl_lpspi->target_aborted) {dev_dbg (fsl_lpspi->dev,"I/O Error in DMA TX interrupted\n" ); -dmaengine_terminate_all (controller->dma_tx); -dmaengine_terminate_all (controller->dma_rx); +dmaengine_terminate_sync (controller->dma_tx); +dmaengine_terminate_sync (controller->dma_rx);fsl_lpspi_reset (fsl_lpspi);return -EINTR ; }
@@ -654,8 +654,8 @@ static int fsl_lpspi_dma_transfer(struct fsl_lpspi->target_aborted) {dev_dbg (fsl_lpspi->dev,"I/O Error in DMA RX interrupted\n" ); -dmaengine_terminate_all (controller->dma_tx); -dmaengine_terminate_all (controller->dma_rx); +dmaengine_terminate_sync (controller->dma_tx); +dmaengine_terminate_sync (controller->dma_rx);fsl_lpspi_reset (fsl_lpspi);return -EINTR ; }
Greg Kroah-Hartman
maintainerPATCH 291/1266 spi: fsl-lpspi: terminate the RX channel on TX prepare failure path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carlos Song <[email protected]>
commit 01980b5da56e573d62798d0ff6c86bcaa2b22cbe upstream.
When dmaengine_prep_slave_sg() fails for the TX channel, the error path terminates the TX DMA channel but leaves the RX channel running. Since the RX channel was already submitted and issued prior to preparing the TX descriptor, returning -EINVAL causes the SPI core to unmap the DMA buffers while the RX DMA engine continues writing to them, leading to potential memory corruption or use-after-free.
Terminate the RX channel before returning on the TX prepare failure path.
--- drivers/spi/spi-fsl-lpspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-fsl-lpspi.c +1 -1
@@ -603,7 +603,7 @@ static int fsl_lpspi_dma_transfer(struct tx->sgl, tx->nents,DMA_MEM_TO_DEV , DMA_PREP_INTERRUPT | DMA_CTRL_ACK);if (!desc_tx) { -dmaengine_terminate_sync (controller->dma_tx); +dmaengine_terminate_sync (controller->dma_rx);return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 292/1266 EDAC/i10nm: Dont fail probing if ADXL is missing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vasily Khoruzhick <[email protected]>
commit e360a6d65bb46c527a5909430a31d640cdd5036e upstream.
ADXL is not present in Coreboot- or Slimbootloader-based BIOSes and as result, the driver fails to probe there.
Since commit 2738c69a8813 ("EDAC/i10nm: Add driver decoder for Ice Lake and Tremont CPUs"), i10nm_edac supports driver decoder. Switch to driver decoding when ADXL is not present.
--- drivers/edac/i10nm_base.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/edac/i10nm_base.c +11 -3
@@ -88,6 +88,7 @@ static struct res_config *res_cfg;static int retry_rd_err_log;static int decoding_via_mca;static bool mem_cfg_2lm; +static bool no_adxl;static u32 offsets_scrub_icx[] = {0x22c60 ,0x22c54 ,0x22c5c ,0x22c58 ,0x22c28 ,0x20ed8 };static u32 offsets_scrub_spr[] = {0x22c60 ,0x22c54 ,0x22f08 ,0x22c58 ,0x22c28 ,0x20ed8 };
@@ -1173,8 +1174,14 @@ static int __init i10nm_init(void) } rc =skx_adxl_get (); -if (rc) - goto fail; +if (rc) { +/* Decoding errors via MCA banks for 2LM isn't supported yet */ +if (rc != -ENODEV || mem_cfg_2lm) + goto fail; +i10nm_printk (KERN_INFO ,"ADXL not found, falling back to MCA-based decoding.\n" ); + no_adxl = true; + decoding_via_mca = true; + }opstate_init ();mce_register_decode_chain (&i10nm_mce_dec);
@@ -1208,7 +1215,8 @@ static void __exit i10nm_exit(void)teardown_i10nm_debug ();mce_unregister_decode_chain (&i10nm_mce_dec); -skx_adxl_put (); +if (!no_adxl) +skx_adxl_put ();skx_remove (); }
Greg Kroah-Hartman
maintainerPATCH 293/1266 watchdog: apple: Add "apple,t8103-wdt" compatible
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Janne Grunau <[email protected]>
commit 14ca4868886f2188401fe06cd7bf01a330b3fb99 upstream.
After discussion with the devicetree maintainers we agreed to not extend lists with the generic compatible "apple,wdt" anymore [1]. Use "apple,t8103-wdt" as base compatible as it is the SoC the driver and bindings were written for.
[1]: https://lore.kernel.org/asahi/[email protected]/
--- drivers/watchdog/apple_wdt.c | 1 + 1 file changed, 1 insertion(+)
drivers/watchdog/apple_wdt.c +1 -0
@@ -191,6 +191,7 @@ static int apple_wdt_probe(struct platfo }static const struct of_device_id apple_wdt_of_match[] = { + { .compatible ="apple,t8103-wdt" }, { .compatible ="apple,wdt" }, {}, };
Greg Kroah-Hartman
maintainerPATCH 294/1266 tracing: Prevent out-of-bounds read in glob matching
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huihui Huang <[email protected]>
commit 0a6070839b1ef276d5b05bedfb787743e140fb17 upstream.
String event fields are not necessarily NUL-terminated, so the filter predicate functions (filter_pred_string(), filter_pred_strloc() and filter_pred_strrelloc()) pass the field length to the regex match callbacks, and the length-aware matchers honour it.
regex_match_glob() was the exception: it ignored the length and called glob_match(), which scans the string until it hits a NUL byte. Some string fields are not NUL-terminated. One example is the dynamic char array of the xfs_* namespace tracepoints, which is copied without a trailing NUL. For such a field, glob matching reads past the end of the event field, causing a KASAN slab-out-of-bounds read in glob_match(), reached via regex_match_glob() and filter_match_preds() from the xfs_lookup tracepoint.
Add a length-bounded glob_match_len() and use it from regex_match_glob() so glob matching always stops at the field boundary. The matching loop is factored into a shared helper so glob_match() keeps its behaviour.
--- include/linux/glob.h | 1 + kernel/trace/trace_events_filter.c | 6 ++---- lib/glob.c | 31 +++++++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 6 deletions(-)
include/linux/glob.h +1 -0
@@ -6,5 +6,6 @@#include <linux/compiler.h> /* For __pure */ bool __pure glob_match (char const *pat,char const *str); +bool __pure glob_match_len (char const *pat,char const *str,size_t len);#endif /* _LINUX_GLOB_H */
kernel/trace/trace_events_filter.c +2 -4
@@ -1056,11 +1056,9 @@ static int regex_match_end(char *str, streturn 0 ; } -static int regex_match_glob (char *str,struct regex *r,int len__maybe_unused ) +static int regex_match_glob (char *str,struct regex *r,int len) { -if (glob_match (r->pattern, str)) -return 1 ; -return 0 ; +return glob_match_len (r->pattern, str, len) ?1 :0 ; }/**
lib/glob.c +29 -2
@@ -9,6 +9,9 @@MODULE_DESCRIPTION ("glob(7) matching" );MODULE_LICENSE ("Dual MIT/GPL" ); +static bool __pure glob_match_str (char const *pat,char const *str, +char const *str_end); +/** * glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) * @pat: Shell-style pattern to match, e.g. "*.[ch]".
@@ -39,6 +42,29 @@ MODULE_LICENSE("Dual MIT/GPL");*/ bool __pure glob_match (char const *pat,char const *str) { +return glob_match_str (pat, str,NULL ); +} +EXPORT_SYMBOL (glob_match); + +/** +* glob_match_len - glob match against a length-bounded string +* @pat: Shell-style pattern to match. +* @str: String to match. Need not be NUL-terminated. +* @len: Number of bytes of @str that may be read. +* +* Like glob_match(), but @str is only read up to @len bytes, so it can be +* used on buffers that are not NUL-terminated (e.g. trace event fields). +* A NUL byte within @len still terminates the string. +*/ +bool __pure glob_match_len (char const *pat,char const *str,size_t len) +{ +return glob_match_str (pat, str, str + len); +} +EXPORT_SYMBOL (glob_match_len); + +static bool __pure glob_match_str (char const *pat,char const *str, +char const *str_end) +{/* * Backtrack to previous * on mismatch and retry starting one * character later in the string. Because * matches all characters
@@ -53,9 +79,11 @@ bool __pure glob_match(char const *pat,* on mismatch, or true after matching the trailing nul bytes. */ for (;;) { -unsigned char c = *str++; +unsigned char c = (str_end && str >= str_end) ?'\0' : *str;unsigned char d = *pat++; + str++; +switch (d) {case '?' :/* Wildcard: anything but nul */ if (c =='\0' )
@@ -120,4 +148,3 @@ backtrack: } } } -EXPORT_SYMBOL (glob_match);
Greg Kroah-Hartman
maintainerPATCH 295/1266 NFSv4: include MAY_WRITE in open permission mask for O_TRUNC
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Coddington <[email protected]>
commit 5140f099ecd8a2f2808b7f7b720ee1bad8468974 upstream.
POSIX requires write permission to truncate a file, so an open() that specifies O_TRUNC must be authorized for write access regardless of the O_ACCMODE access mode.
nfs_open_permission_mask() builds the access mask passed to nfs_may_open(), which is the local authorization gate for OPENs the client serves itself from a cached write delegation via the can_open_delegated() path in nfs4_try_open_cached(). The mask is derived from O_ACCMODE alone, so an open(O_RDONLY | O_TRUNC) against a file the caller cannot write requests only MAY_READ and passes the local check. The OPEN is then satisfied locally and the truncation is issued to the server as a SETATTR(size=0) over the delegation stateid, which the server accepts under standard write-delegation semantics. POSIX requires that this open fail with EACCES.
Include MAY_WRITE in the mask whenever O_TRUNC is set so the local check matches the access the server would have enforced.
--- fs/nfs/dir.c | 2 ++ 1 file changed, 2 insertions(+)
fs/nfs/dir.c +2 -0
@@ -3275,6 +3275,8 @@ static int nfs_open_permission_mask(int mask |=MAY_READ ;if ((openflags &O_ACCMODE ) !=O_RDONLY ) mask |=MAY_WRITE ; +if (openflags &O_TRUNC ) + mask |=MAY_WRITE ; }return mask;
Greg Kroah-Hartman
maintainerPATCH 296/1266 module: decompress: check return value of module_extend_max_pages()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrii Kuchmenko <[email protected]>
commit 786d2d84416a9a1c1a47b71a68d679d886284be2 upstream.
module_extend_max_pages() calls kvrealloc() internally and returns -ENOMEM on allocation failure. The return value is never checked.
If the initial allocation fails, info->pages remains NULL and info->max_pages remains 0. Subsequent calls to module_get_next_page() will attempt to dynamically grow the array by calling module_extend_max_pages(info, 0) since info->used_pages is 0. This results in kvrealloc(NULL, 0) returning ZERO_SIZE_PTR, which is treated as a success, leading to a dereference of ZERO_SIZE_PTR and a kernel oops.
Fix: add the missing error check after module_extend_max_pages() and return immediately on failure. This matches the pattern used by every other kvrealloc() caller in the module loading path.
--- kernel/module/decompress.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/module/decompress.c +2 -0
@@ -307,6 +307,8 @@ int module_decompress(struct load_info **/ n_pages =DIV_ROUND_UP (size,PAGE_SIZE ) *2 ; error =module_extend_max_pages (info, n_pages); +if (error) +return error; data_size =MODULE_DECOMPRESS_FN (info, buf, size);if (data_size <0 ) {
Greg Kroah-Hartman
maintainerPATCH 297/1266 exfat: bound uniname advance in exfat_find_dir_entry()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 3a1230e7b043c62737b05a3e9275ca83a43ad20a upstream.
In exfat_find_dir_entry(), each TYPE_EXTEND (file name) entry advances the output pointer by a fixed amount while the loop guard only tracks the accumulated name length:
if (++order == 2) uniname = p_uniname->name; else uniname += EXFAT_FILE_NAME_LEN; len = exfat_extract_uni_name(ep, entry_uniname); name_len += len; unichar = *(uniname+len); *(uniname+len) = 0x0;
uniname grows by EXFAT_FILE_NAME_LEN (15) per name entry, but name_len grows only by the actual extracted length, which is shorter when a name fragment contains an early NUL. The only guard isname_len >= MAX_NAME_LENGTH, so a crafted directory with many short name fragments lets uniname run far past the p_uniname->name[MAX_NAME_LENGTH + 3] buffer while name_len stays small, causing an out-of-bounds read and write at *(uniname+len).
The sibling extractor exfat_get_uniname_from_ext_entry() already stops on a short fragment (the lockstep len != EXFAT_FILE_NAME_LEN guard added in commit d42334578eba ("exfat: check if filename entries exceeds max filename length")); exfat_find_dir_entry() never got the equivalent. Track the per-entry write offset as a count and reject a fragment once the offset, or the offset plus the extracted length, would exceed MAX_NAME_LENGTH, before forming the output pointer.
--- fs/exfat/dir.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
fs/exfat/dir.c +8 -5
@@ -1081,6 +1081,7 @@ rewind:if (entry_type ==TYPE_EXTEND ) {unsigned short entry_uniname[16 ], unichar; +unsigned int offset;if (step !=DIRENT_STEP_NAME || name_len >=MAX_NAME_LENGTH ) {
@@ -1089,13 +1090,15 @@ rewind:continue ; } -if (++order ==2 ) - uniname = p_uniname->name; -else - uniname +=EXFAT_FILE_NAME_LEN ; - + offset = (++order -2 ) *EXFAT_FILE_NAME_LEN ; len =exfat_extract_uni_name (ep, entry_uniname);brelse (bh); +if (offset >MAX_NAME_LENGTH || + len >MAX_NAME_LENGTH - offset) { + step =DIRENT_STEP_FILE ; +continue ; + } + uniname = p_uniname->name + offset; name_len += len; unichar = *(uniname+len);
Greg Kroah-Hartman
maintainerPATCH 298/1266 NTB: epf: Fix request_irq() unwind in ntb_epf_init_isr()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <[email protected]>
commit fcba26efe5efc7441f5505f4ccc69791214b40be upstream.
ntb_epf_init_isr() requests multiple MSI/MSI-X vectors in a loop. If request_irq() fails part-way through, it jumps straight to pci_free_irq_vectors() without freeing already requested IRQs.
Fix the error path by freeing any successfully requested IRQs before releasing the vectors.
--- drivers/ntb/hw/epf/ntb_hw_epf.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
drivers/ntb/hw/epf/ntb_hw_epf.c +4 -6
@@ -357,7 +357,7 @@ static int ntb_epf_init_isr(struct ntb_e 0, "ntb_epf", ndev);if (ret) {dev_err (dev,"Failed to request irq\n" ); - goto err_request_irq; + goto err_free_irq; } }
@@ -367,16 +367,14 @@ static int ntb_epf_init_isr(struct ntb_e argument | irq);if (ret) {dev_err (dev,"Failed to configure doorbell\n" ); - goto err_configure_db; + goto err_free_irq; }return 0 ; -err_configure_db: -for (i =0 ; i < ndev->db_count +1 ; i++) +err_free_irq: +while (i--)free_irq (pci_irq_vector (pdev, i), ndev); - -err_request_irq:pci_free_irq_vectors (pdev);return ret;
Greg Kroah-Hartman
maintainerPATCH 299/1266 KVM: VMX: Refresh GUEST_PENDING_DBG_EXCEPTIONS.BS on all injected #DBs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit c5bad4fa2d5dfd8c25140051a9807eba387a19b8 upstream.
Move KVM's stuffing of GUEST_PENDING_DBG_EXCEPTIONS.BS when RFLAGS.TF=1 and MOV/POP SS or STI blocking is active into the exception injection code so that KVM fixes up the VMCS for all injected #DBs, not only those that are reflected back into the guest after #DB interception. E.g. if KVM queues a #DB in the emulator, or more importantly if userspace does save/restore exactly on the #DB+shadow boundary, then KVM needs to massage the VMCS to avoid the VM-Entry consistency check.
Opportunistically update the wording of the comment to describe the behavior as a workaround of flawed CPU behavior/architecture, to make it clear that the *only* thing KVM is doing is fudging around a consistency check. Per the SDM:
There are no pending debug exceptions after VM entry if any of the following are true:
* The VM entry is vectoring with one of the following interruption
types: external interrupt, non-maskable interrupt (NMI), hardware exception, or privileged software exception.
I.e. forcing GUEST_PENDING_DBG_EXCEPTIONS.BS does *not* impact guest- visible behavior.
--- arch/x86/kvm/vmx/vmx.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-)
arch/x86/kvm/vmx/vmx.c +18 -17
@@ -1810,6 +1810,24 @@ static void vmx_inject_exception(structu32 intr_info = ex->vector |INTR_INFO_VALID_MASK ;struct vcpu_vmx *vmx =to_vmx (vcpu); +/* +* When injecting a #DB, single-stepping is enabled in RFLAGS, and STI +* or MOV-SS blocking is active, set vmcs.PENDING_DBG_EXCEPTIONS.BS to +* prevent a false positive from VM-Entry consistency check. VM-Entry +* asserts that a single-step #DB _must_ be pending in this scenario, +* as the previous instruction cannot have toggled RFLAGS.TF 0=>1 +* (because STI and POP/MOV don't modify RFLAGS), therefore the one +* instruction delay when activating single-step breakpoints must have +* already expired. However, the CPU isn't smart enough to peek at +* vmcs.VM_ENTRY_INTR_INFO_FIELD and so doesn't realize that yes, there +* is indeed a #DB pending/imminent. +*/ +if (ex->vector ==DB_VECTOR && + (vmx_get_rflags (vcpu) &X86_EFLAGS_TF ) && +vmx_get_interrupt_shadow (vcpu)) +vmcs_writel (GUEST_PENDING_DBG_EXCEPTIONS , +vmcs_readl (GUEST_PENDING_DBG_EXCEPTIONS ) |DR6_BS ); +kvm_deliver_exception_payload (vcpu, ex);if (ex->has_error_code) {
@@ -5281,26 +5299,9 @@ static int handle_exception_nmi(struct k* avoid single-step #DB and MTF updates, as ICEBP is * higher priority. Note, skipping ICEBP still clears * STI and MOVSS blocking. -* -* For all other #DBs, set vmcs.PENDING_DBG_EXCEPTIONS.BS -* if single-step is enabled in RFLAGS and STI or MOVSS -* blocking is active, as the CPU doesn't set the bit -* on VM-Exit due to #DB interception. VM-Entry has a -* consistency check that a single-step #DB is pending -* in this scenario as the previous instruction cannot -* have toggled RFLAGS.TF 0=>1 (because STI and POP/MOV -* don't modify RFLAGS), therefore the one instruction -* delay when activating single-step breakpoints must -* have already expired. Note, the CPU sets/clears BS -* as appropriate for all other VM-Exits types. */ if (is_icebp (intr_info))WARN_ON (!skip_emulated_instruction (vcpu)); -else if ((vmx_get_rflags (vcpu) &X86_EFLAGS_TF ) && - (vmcs_read32 (GUEST_INTERRUPTIBILITY_INFO ) & - (GUEST_INTR_STATE_STI |GUEST_INTR_STATE_MOV_SS ))) -vmcs_writel (GUEST_PENDING_DBG_EXCEPTIONS , -vmcs_readl (GUEST_PENDING_DBG_EXCEPTIONS ) |DR6_BS );kvm_queue_exception_p (vcpu,DB_VECTOR , dr6);return 1 ;
Greg Kroah-Hartman
maintainerPATCH 300/1266 KVM: VMX: Grab vmcs12 on CR8 interception update iff vCPU is in guest mode
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 7ef78d71ca713d8c00f7c34ddcf276c808143f77 upstream.
When updating CR8 intercepts, get vmcs12 if and only if the vCPU is in guest mode so that a future change can have update CR8 intercepts during vCPU creation, without running afoul of get_vmcs12()'s lockdep assertion.
------------[ cut here ]------------ debug_locks && !(lock_is_held(&(&vcpu->mutex)->dep_map) || !refcount_read(&vcpu->kvm->users_count)) WARNING: arch/x86/kvm/vmx/nested.h:61 at get_vmcs12 arch/x86/kvm/vmx/nested.h:60 [inline], CPU#0: syz.2.19/5879 WARNING: arch/x86/kvm/vmx/nested.h:61 at vmx_update_cr8_intercept+0x3de/0x4e0 arch/x86/kvm/vmx/vmx.c:6879, CPU#0: syz.2.19/5879 Modules linked in: CPU: 0 UID: 0 PID: 5879 Comm: syz.2.19 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 RIP: 0010:get_vmcs12 arch/x86/kvm/vmx/nested.h:60 [inline] RIP: 0010:vmx_update_cr8_intercept+0x3de/0x4e0 arch/x86/kvm/vmx/vmx.c:6879 Call Trace: <TASK> apic_update_ppr arch/x86/kvm/lapic.c:984 [inline] kvm_lapic_reset+0x1c24/0x2980 arch/x86/kvm/lapic.c:3023 kvm_vcpu_reset+0x44c/0x1bf0 arch/x86/kvm/x86.c:12986 kvm_arch_vcpu_create+0x746/0x8b0 arch/x86/kvm/x86.c:12847 kvm_vm_ioctl_create_vcpu+0x428/0x930 virt/kvm/kvm_main.c:4201 kvm_vm_ioctl+0x893/0xd50 virt/kvm/kvm_main.c:5159 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:597 [inline] __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f </TASK>
No functional change intended.
Message-ID: <[email protected]>
--- arch/x86/kvm/vmx/vmx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/x86/kvm/vmx/vmx.c +1 -2
@@ -6701,11 +6701,10 @@ static noinstr void vmx_l1d_flush(structstatic void vmx_update_cr8_intercept (struct kvm_vcpu *vcpu,int tpr,int irr) { -struct vmcs12 *vmcs12 =get_vmcs12 (vcpu);int tpr_threshold;if (is_guest_mode (vcpu) && -nested_cpu_has (vmcs12,CPU_BASED_TPR_SHADOW )) +nested_cpu_has (get_vmcs12 (vcpu),CPU_BASED_TPR_SHADOW ))return ; tpr_threshold = (irr ==-1 || tpr < irr) ?0 : irr;
Greg Kroah-Hartman
maintainerPATCH 301/1266 udmabuf: fix DMA direction mismatch in release_udmabuf()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikhail Gavrilov <[email protected]>
commit fb7b1a0ab25a6077d26cb3829e31743972d4f31d upstream.
begin_cpu_udmabuf() maps the sg_table with the caller-provided direction (e.g., DMA_TO_DEVICE for a write-only sync), and caches it in ubuf->sg for reuse. However, release_udmabuf() always unmaps this sg_table with a hardcoded DMA_BIDIRECTIONAL, regardless of the direction that was originally used for the mapping.
With CONFIG_DMA_API_DEBUG=y this produces:
DMA-API: misc udmabuf: device driver frees DMA memory with different direction [device address=0x000000044a123000] [size=4096 bytes] [mapped with DMA_TO_DEVICE] [unmapped with DMA_BIDIRECTIONAL]
The issue was found during video playback when GStreamer performed a write-only DMA_BUF_IOCTL_SYNC on a udmabuf. It can be reproduced with CONFIG_DMA_API_DEBUG=y by creating a udmabuf from a memfd, performing a write-only sync (DMA_BUF_SYNC_WRITE without DMA_BUF_SYNC_READ), and closing the file descriptor.
Fix this by storing the DMA direction used when the sg_table is first created in begin_cpu_udmabuf(), and passing that same direction to put_sg_table() in release_udmabuf().
--- drivers/dma-buf/udmabuf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/dma-buf/udmabuf.c +4 -1
@@ -27,6 +27,7 @@ struct udmabuf {pgoff_t pagecount;struct page **pages;struct sg_table *sg; +enum dma_data_direction sg_dir;struct miscdevice *device; };
@@ -139,7 +140,7 @@ static void release_udmabuf(struct dma_bpgoff_t pg;if (ubuf->sg) -put_sg_table (dev, ubuf->sg,DMA_BIDIRECTIONAL ); +put_sg_table (dev, ubuf->sg, ubuf->sg_dir);for (pg =0 ; pg < ubuf->pagecount; pg++)put_page (ubuf->pages[pg]);
@@ -159,6 +160,8 @@ static int begin_cpu_udmabuf(struct dma_if (IS_ERR (ubuf->sg)) { ret =PTR_ERR (ubuf->sg); ubuf->sg =NULL ; + }else { + ubuf->sg_dir = direction; } }else {dma_sync_sgtable_for_cpu (dev, ubuf->sg, direction);
Greg Kroah-Hartman
maintainerPATCH 302/1266 i2c: core: fix adapter deregistration race
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit b1a58ed9eab146b36f41a55db8f5d7ce9fdedf3f upstream.
Adapters can be looked up by their id using i2c_get_adapter() which takes a reference to the embedded struct device.
Remove the adapter from the IDR before tearing it down during deregistration (and on registration failure) to make sure its resources are not accessed after having been freed (e.g. the device name).
--- drivers/i2c/i2c-core-base.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/i2c/i2c-core-base.c +7 -2
@@ -1563,7 +1563,7 @@ static int i2c_register_adapter(struct i res =device_add (&adap->dev);if (res) {pr_err ("adapter '%s': can't register device (%d)\n" , adap->name, res); - goto err_remove_debugfs; + goto err_replace_id; } res =i2c_setup_smbus_alert (adap);
@@ -1607,7 +1607,10 @@ static int i2c_register_adapter(struct i out_reg:i2c_deregister_clients (adap);device_del (&adap->dev); -err_remove_debugfs: +err_replace_id: +mutex_lock (&core_lock); +idr_replace (&i2c_adapter_idr,NULL , adap->nr); +mutex_unlock (&core_lock);debugfs_remove_recursive (adap->debugfs);init_completion (&adap->dev_released);put_device (&adap->dev);
@@ -1797,6 +1800,8 @@ void i2c_del_adapter(struct i2c_adapter/* First make sure that this adapter was ever added */ mutex_lock (&core_lock); found =idr_find (&i2c_adapter_idr, adap->nr); +if (found == adap) +idr_replace (&i2c_adapter_idr,NULL , adap->nr);mutex_unlock (&core_lock);if (found != adap) {pr_debug ("attempting to delete unregistered adapter [%s]\n" , adap->name);
Greg Kroah-Hartman
maintainerPATCH 303/1266 i2c: mpc: Fix timeout calculations
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
commit 2e9a7f68329be41792c0b123c28e6c53c2fa2249 upstream.
At first glance the harmless cleanup of the driver does nothing bad. However, as the operator precedence list states the '*' (multiplication) and '/' division operators have order 5 with left-to-right associativity the *= has order 17 and associativity right-to-left. It wouldn't be a problem to replace
foo = foo * HZ / 1000000;
with
foo *= HZ / 1000000;
if HZ constant is in Hertz. The problem is that in the Linux kernel HZ is defined in jiffy units, which is order of magnitude smaller than a million. That's why operator precedence has a crucial role here. Fix the regression by reverting pre-optimized calculations.
--- drivers/i2c/busses/i2c-mpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-mpc.c +1 -1
@@ -857,7 +857,7 @@ static int fsl_i2c_probe(struct platform "fsl,timeout", &mpc_ops.timeout);if (!result) { - mpc_ops.timeout *=HZ /1000000 ; + mpc_ops.timeout = mpc_ops.timeout *HZ /1000000 ;if (mpc_ops.timeout <5 ) mpc_ops.timeout =5 ; }else {
Greg Kroah-Hartman
maintainerPATCH 304/1266 i2c: stm32f7: truncate clock period instead of rounding it
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guillermo Rodríguez <[email protected]>
commit 111bb7f9f4a90b32e495d70a607c67b137f3074a upstream.
stm32f7_i2c_compute_timing() derives the I2C clock source period (i2cclk) with DIV_ROUND_CLOSEST, which may round it up. When the period is overestimated, all timings computed from it (SCLDEL, SDADEL, SCLL, SCLH) come out shorter on the wire than calculated, and the resulting bus rate can exceed the requested speed, violating the I2C specification minimums for tLOW and tHIGH.
For example, with a 104.45 MHz clock source (e.g. PCLK1, the reset-default I2C clock source on STM32MP1), i2cclk is rounded from 9.574 ns up to 10 ns. Requesting a 400 kHz fast mode bus with 72/27 ns rise/fall times and no analog/digital filters then produces an actual bus rate of 415.6 kHz with tLOW = 1254 ns, violating both the 400 kHz maximum rate and the 1300 ns tLOW minimum of the specification.
Truncate the period instead, so that it can only be underestimated. The error then falls on the safe side: the programmed timings come out slightly longer than computed and the bus runs marginally below the target rate (375.3 kHz in the example above) while meeting the specification.
i2cbus is left rounded-to-closest: it is only used as the target of the clk_error comparison and is never multiplied into the programmed timings, so nearest rounding remains accurate there.
--- drivers/i2c/busses/i2c-stm32f7.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +7 -2
@@ -450,8 +450,13 @@ static int stm32f7_i2c_compute_timing(st {struct stm32f7_i2c_spec *specs;u32 p_prev =STM32F7_PRESC_MAX ; -u32 i2cclk =DIV_ROUND_CLOSEST (NSEC_PER_SEC , - setup->clock_src); +/* +* Truncate instead of rounding to closest: if the clock period is +* overestimated, the computed SCL timings will come out shorter on +* the wire, which can push the bus above the target rate and below +* the spec's tLOW/tHIGH minimums. +*/ +u32 i2cclk =NSEC_PER_SEC / setup->clock_src;u32 i2cbus =DIV_ROUND_CLOSEST (NSEC_PER_SEC , setup->speed_freq);u32 clk_error_prev = i2cbus;
Greg Kroah-Hartman
maintainerPATCH 305/1266 Input: synaptics-rmi4 - unregister function handlers on physical driver registration failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit 6251f7d3472c0409e30f8d6a24f10d33d12e3f9a upstream.
If rmi_register_physical_driver() fails, the current error path unregisters only the RMI bus. The function handlers registered earlier remain registered with the driver core.
Add a separate error path to unregister the function handlers before unregistering the bus in this failure case.
--- drivers/input/rmi4/rmi_bus.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/input/rmi4/rmi_bus.c +3 -1
@@ -448,11 +448,13 @@ static int __init rmi_bus_init(void)if (error) {pr_err ("%s: error registering the RMI physical driver: %d\n" , __func__, error); - goto err_unregister_bus; + goto err_unregister_function_handlers; }return 0 ; +err_unregister_function_handlers: +rmi_unregister_function_handlers (); err_unregister_bus:bus_unregister (&rmi_bus_type);return error;
Greg Kroah-Hartman
maintainerPATCH 306/1266 Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 57c10915f2c16c90e0d46ad00876bf39ece40fc2 upstream.
rmi_f3a_initialize() takes the GPIO count from the device query register (f3a->gpio_count = buf & RMI_F3A_GPIO_COUNT, range 0..127). rmi_f3a_map_gpios() then allocates gpio_key_map with min(gpio_count, TRACKSTICK_RANGE_END) == at most 6 entries, but rmi_f3a_attention() iterates the full gpio_count and dereferences gpio_key_map[i], and input->keycodemax is set to the full gpio_count while input->keycode points at the 6-entry allocation.
A device that reports gpio_count > 6 therefore causes an out-of-bounds read of gpio_key_map[] on every attention interrupt, and out-of-bounds accesses through the input core's default keymap ioctls: EVIOCGKEYCODE reads past the buffer (leaking adjacent slab memory to user space) and EVIOCSKEYCODE writes a caller-controlled value past it, for any process able to open the evdev node, since input_default_getkeycode() and input_default_setkeycode() only bound the index against keycodemax.
Size the keymap for the full gpio_count. The mapping loop is unchanged:
it still assigns only the first min(gpio_count, TRACKSTICK_RANGE_END) entries; the remaining slots stay KEY_RESERVED (devm_kcalloc zero-fills) and are skipped when reporting.
--- drivers/input/rmi4/rmi_f3a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/rmi4/rmi_f3a.c +1 -1
@@ -132,7 +132,7 @@ static int rmi_f3a_map_gpios(struct rmi_int button_count =min_t (u8, f3a->gpio_count,TRACKSTICK_RANGE_END ); f3a->gpio_key_map =devm_kcalloc (&fn->dev, - button_count, + f3a->gpio_count,sizeof (f3a->gpio_key_map[0 ]),GFP_KERNEL );if (!f3a->gpio_key_map) {
Greg Kroah-Hartman
maintainerPATCH 307/1266 Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit d577e46785d45484b2ab7e7309c49b18764bf56c upstream.
rmi_f30_map_gpios() allocates gpioled_key_map with min(gpioled_count, TRACKSTICK_RANGE_END) == at most 6 entries, but rmi_f30_attention() iterates the full f30->gpioled_count (device query register, range 0..31) and dereferences gpioled_key_map[i], and input->keycodemax is set to the full gpioled_count while input->keycode points at the 6-entry allocation.
A device that reports gpioled_count > 6 with GPIO support enabled therefore causes an out-of-bounds read on the attention interrupt and out-of-bounds read/write through the EVIOCGKEYCODE/EVIOCSKEYCODE ioctls, which bound the index only against keycodemax. This is the same defect as the F3A handler, which was copied from F30.
Size the keymap for the full gpioled_count; the mapping loop still assigns only the first min(gpioled_count, TRACKSTICK_RANGE_END) entries.
--- drivers/input/rmi4/rmi_f30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/rmi4/rmi_f30.c +1 -1
@@ -233,7 +233,7 @@ static int rmi_f30_map_gpios(struct rmi_int button_count =min_t (u8, f30->gpioled_count,TRACKSTICK_RANGE_END ); f30->gpioled_key_map =devm_kcalloc (&fn->dev, - button_count, + f30->gpioled_count,sizeof (f30->gpioled_key_map[0 ]),GFP_KERNEL );if (!f30->gpioled_key_map) {
Greg Kroah-Hartman
maintainerPATCH 308/1266 Input: elan_i2c - prevent division by zero and arithmetic underflow
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ranjan Kumar <[email protected]>
commit df2b818fa009c10ff6ba875a1663ff001cda9558 upstream.
The Elan I2C touchpad driver queries the device for its physical dimensions and trace counts to calculate the device resolution and width. However, if the device firmware or device tree provides invalid zero values for x_traces or y_traces, it results in a fatal division-by-zero exception leading to a kernel panic during device probe.
Add checks to ensure these parameters are non-zero before performing the division. If invalid trace values are detected, fall back to a safe default of 1.
Additionally, prevent an arithmetic underflow in the touch reporting logic. Previously, if the calculated or fallback width was smaller than ETP_FWIDTH_REDUCE (90), the subtraction would underflow, resulting in a massive unsigned integer being reported to userspace. Clamp the adjusted width to a minimum of 0 to safely handle small physical dimensions and fallback scenarios.
Completing the probe with safe fallback values ensures the sysfs nodes are created, keeping the firmware update path intact so a recovery firmware can be flashed to the device.
--- drivers/input/mouse/elan_i2c_core.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-)
drivers/input/mouse/elan_i2c_core.c +30 -6
@@ -424,8 +424,17 @@ static int elan_query_device_parameters(if (error)return error; } - data->width_x = data->max_x / x_traces; - data->width_y = data->max_y / y_traces; + +if (!x_traces || !y_traces) { +dev_warn (&client->dev, +"invalid trace numbers: x=%u, y=%u\n" , + x_traces, y_traces); + data->width_x =1 ; + data->width_y =1 ; + }else { + data->width_x = data->max_x / x_traces; + data->width_y = data->max_y / y_traces; + } if (device_property_read_u32(&client->dev, "touchscreen-x-mm", &x_mm) ||
@@ -439,8 +448,16 @@ static int elan_query_device_parameters( data->x_res =elan_convert_resolution (hw_x_res, data->pattern); data->y_res =elan_convert_resolution (hw_y_res, data->pattern); }else { - data->x_res = (data->max_x +1 ) / x_mm; - data->y_res = (data->max_y +1 ) / y_mm; +if (unlikely (x_mm ==0 || y_mm ==0 )) { +dev_warn (&client->dev, +"invalid physical dimensions: x_mm=%u, y_mm=%u\n" , + x_mm, y_mm); + data->x_res =1 ; + data->y_res =1 ; + }else { + data->x_res = (data->max_x +1 ) / x_mm; + data->y_res = (data->max_y +1 ) / y_mm; + } }if (device_property_read_bool (&client->dev,"elan,clickpad" ))
@@ -959,6 +976,7 @@ static void elan_report_contact(struct eif (data->report_features &ETP_FEATURE_REPORT_MK ) {unsigned int mk_x, mk_y, area_x, area_y; +int adj_width_x, adj_width_y;u8 mk_data = high_precision ? packet[ETP_MK_DATA_OFFSET + contact_num] : finger_data[3 ];
@@ -970,8 +988,14 @@ static void elan_report_contact(struct e* To avoid treating large finger as palm, let's reduce * the width x and y per trace. */ - area_x = mk_x * (data->width_x -ETP_FWIDTH_REDUCE ); - area_y = mk_y * (data->width_y -ETP_FWIDTH_REDUCE ); + + adj_width_x = data->width_x >ETP_FWIDTH_REDUCE ? + data->width_x -ETP_FWIDTH_REDUCE :0 ; + adj_width_y = data->width_y >ETP_FWIDTH_REDUCE ? + data->width_y -ETP_FWIDTH_REDUCE :0 ; + + area_x = mk_x * adj_width_x; + area_y = mk_y * adj_width_y;input_report_abs (input,ABS_TOOL_WIDTH , mk_x); input_report_abs(input, ABS_MT_TOUCH_MAJOR,
Greg Kroah-Hartman
maintainerPATCH 309/1266 Input: goodix - clamp the device-reported contact count
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 5ed62a96e06be4e94b8296b7932afee550a70e04 upstream.
goodix_ts_read_input_report() copies the number of touch points reported by the device into an on-stack buffer
u8 point_data[2 + GOODIX_MAX_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
which is sized for at most GOODIX_MAX_CONTACTS (10) contacts. The only runtime check bounds the per-interrupt count against ts->max_touch_num, but that value is taken verbatim from a 4-bit field of the device configuration block and is never clamped:
ts->max_touch_num = ts->config[MAX_CONTACTS_LOC] & 0x0f;
The nibble can be 0..15, so a malfunctioning, malicious or counterfeit controller (or an attacker tampering with the I2C bus) can advertise up to 15 contacts. goodix_ts_read_input_report() then accepts a touch_num of up to 15 and the second goodix_i2c_read() writes ts->contact_size * (touch_num - 1) bytes past the one-contact header into point_data - up to 30 bytes (45 with the 9-byte report format) beyond the 92-byte buffer: a stack out-of-bounds write.
Clamp max_touch_num to GOODIX_MAX_CONTACTS, the number of contacts point_data[] is sized for, when reading it from the configuration.
--- drivers/input/touchscreen/goodix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/input/touchscreen/goodix.c +2 -1
@@ -1056,7 +1056,8 @@ static void goodix_read_config(struct go } ts->int_trigger_type = ts->config[TRIGGER_LOC ] &0x03 ; - ts->max_touch_num = ts->config[MAX_CONTACTS_LOC ] &0x0f ; + ts->max_touch_num =min (ts->config[MAX_CONTACTS_LOC ] &0x0f , +GOODIX_MAX_CONTACTS ); x_max =get_unaligned_le16 (&ts->config[RESOLUTION_LOC ]); y_max =get_unaligned_le16 (&ts->config[RESOLUTION_LOC +2 ]);
Greg Kroah-Hartman
maintainerPATCH 310/1266 Input: iforce - bound the device-reported force-feedback effect index
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 0e9943d2e4c63496b6ca84bc66fd3c71d40558e2 upstream.
iforce_process_packet() handles a status report (packet id 0x02) by taking a force-feedback effect index straight from the device wire and using it to address the per-effect state array:
i = data[1] & 0x7f;
if (data[1] & 0x80) {
if (!test_and_set_bit(FF_CORE_IS_PLAYED,
iforce->core_effects[i].flags))
...
} else if (test_and_clear_bit(FF_CORE_IS_PLAYED,
iforce->core_effects[i].flags)) {
...
}The index is masked only with 0x7f, so it ranges 0..127, but core_effects[] holds only IFORCE_EFFECTS_MAX (32) entries. For an index of 32..127 the test_and_set_bit()/test_and_clear_bit() is an out-of-bounds single-bit read-modify-write past the array. core_effects[] is the second-to-last member of struct iforce, so the write lands in the trailing members and beyond the embedding kzalloc()'d iforce_serio / iforce_usb object.
data[1] is unvalidated device payload on both transports (the USB interrupt endpoint and serio), and the status path is not gated on force feedback being present, so a malicious or counterfeit device can set or clear a bit at an attacker-chosen offset past the object.
Reject an out-of-range index instead of indexing with it. Bound against the array dimension IFORCE_EFFECTS_MAX rather than dev->ff->max_effects so the check guarantees memory safety regardless of how many effects the device registered. A legitimate "effect started/stopped" status always carries an index below IFORCE_EFFECTS_MAX, so well-formed devices are unaffected; the neighbouring mark_core_as_ready() loop is already bounded and is left untouched.
--- drivers/input/joystick/iforce/iforce-packets.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
drivers/input/joystick/iforce/iforce-packets.c +11 -7
@@ -192,14 +192,18 @@ void iforce_process_packet(struct iforce/* Check if an effect was just started or stopped */ i = data[1 ] &0x7f ; -if (data[1 ] &0x80 ) { -if (!test_and_set_bit (FF_CORE_IS_PLAYED , iforce->core_effects[i].flags)) { -/* Report play event */ -input_report_ff_status (dev, i,FF_STATUS_PLAYING ); +if (i <IFORCE_EFFECTS_MAX ) { +if (data[1 ] &0x80 ) { +if (!test_and_set_bit (FF_CORE_IS_PLAYED , + iforce->core_effects[i].flags)) { +/* Report play event */ +input_report_ff_status (dev, i,FF_STATUS_PLAYING ); + } + }else if (test_and_clear_bit (FF_CORE_IS_PLAYED , + iforce->core_effects[i].flags)) { +/* Report stop event */ +input_report_ff_status (dev, i,FF_STATUS_STOPPED ); } - }else if (test_and_clear_bit (FF_CORE_IS_PLAYED , iforce->core_effects[i].flags)) { -/* Report stop event */ -input_report_ff_status (dev, i,FF_STATUS_STOPPED ); }for (j =3 ; j < len; j +=2 )
Greg Kroah-Hartman
maintainerPATCH 311/1266 Input: mms114 - fix touch indexing for MMS134S and MMS136
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit a6ac4e24c1a8a533bb61035184fdcc7eede4cc8d upstream.
The MMS134S and MMS136 touch controllers have an event size of 6 bytes rather than 8 bytes. When __mms114_read_reg() reads the touch data packet from the device into the touch buffer, the events are packed tightly at 6-byte intervals. However, the driver iterates through the events using standard C array indexing (touch[index]), where each element is sizeof(struct mms114_touch) (8 bytes) apart. As a result, any touch events beyond the first one are read from incorrect offsets and parsed improperly.
Fix this by explicitly calculating the byte offset for each touch event based on the device's specific event size.
--- drivers/input/touchscreen/mms114.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/input/touchscreen/mms114.c +12 -6
@@ -218,7 +218,9 @@ static irqreturn_t mms114_interrupt(intstruct i2c_client *client = data->client;struct input_dev *input_dev = data->input_dev;struct mms114_touch touch[MMS114_MAX_TOUCH ]; +struct mms114_touch *t;int packet_size; +int event_size;int touch_size;int index;int error;
@@ -236,9 +238,11 @@ static irqreturn_t mms114_interrupt(int/* MMS136 has slightly different event size */ if (data->type ==TYPE_MMS134S || data->type ==TYPE_MMS136 ) - touch_size = packet_size /MMS136_EVENT_SIZE ; + event_size =MMS136_EVENT_SIZE ;else - touch_size = packet_size /MMS114_EVENT_SIZE ; + event_size =MMS114_EVENT_SIZE ; + + touch_size = packet_size / event_size; error =__mms114_read_reg (data,MMS114_INFORMATION , packet_size, (u8 *)touch);
@@ -246,18 +250,20 @@ static irqreturn_t mms114_interrupt(int goto out;for (index =0 ; index < touch_size; index++) { -switch (touch[index].type) { + t = (struct mms114_touch *)((u8 *)touch + index * event_size); + +switch (t->type) {case MMS114_TYPE_TOUCHSCREEN : -mms114_process_mt (data, touch + index); +mms114_process_mt (data, t);break ;case MMS114_TYPE_TOUCHKEY : -mms114_process_touchkey (data, touch + index); +mms114_process_touchkey (data, t);break ;default :dev_err (&client->dev,"Wrong touch type (%d)\n" , - touch[index].type); + t->type);break ; } }
Greg Kroah-Hartman
maintainerPATCH 312/1266 Input: touchwin - reset the packet index on every complete packet
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 478cdd736f2ce3114f90e775d7358136d3977b94 upstream.
tw_interrupt() accumulates each non-zero serial byte into a fixed three-byte buffer with a running index that is only reset once a full packet has been received *and* the device's two Y bytes agree:
tw->data[tw->idx++] = data;
if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
...
tw->idx = 0;
}The reset is gated on tw->data[1] == tw->data[2], a value the device controls. A malicious, malfunctioning or counterfeit Touchwindow peripheral can stream non-zero bytes whose 2nd and 3rd bytes differ: the index reaches TW_LENGTH without the equality holding, is never reset, and keeps growing, so tw->data[tw->idx++] walks off the end of the three-byte array and the rest of the heap-allocated struct tw, one attacker-chosen byte at a time -- an unbounded, device-driven heap out-of-bounds write.
Reset the index on every completed packet and report an event only when the two Y bytes match, like the other serio touchscreen drivers do.
--- drivers/input/touchscreen/touchwin.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
drivers/input/touchscreen/touchwin.c +9 -6
@@ -63,12 +63,15 @@ static irqreturn_t tw_interrupt(struct sif (data) {/* touch */ tw->touched =1 ; tw->data[tw->idx++] = data; -/* verify length and that the two Y's are the same */ -if (tw->idx ==TW_LENGTH && tw->data[1 ] == tw->data[2 ]) { -input_report_abs (dev,ABS_X , tw->data[0 ]); -input_report_abs (dev,ABS_Y , tw->data[1 ]); -input_report_key (dev,BTN_TOUCH ,1 ); -input_sync (dev); +/* a full packet ends the accumulation, valid or not */ +if (tw->idx ==TW_LENGTH ) { +/* report only if the two Y's are the same */ +if (tw->data[1 ] == tw->data[2 ]) { +input_report_abs (dev,ABS_X , tw->data[0 ]); +input_report_abs (dev,ABS_Y , tw->data[1 ]); +input_report_key (dev,BTN_TOUCH ,1 ); +input_sync (dev); + } tw->idx =0 ; } }else if (tw->touched) {/* untouch */
Greg Kroah-Hartman
maintainerPATCH 313/1266 Input: mms114 - reject an oversized device packet size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 66725039f7090afe14c31bd259e2059a68f04023 upstream.
mms114_interrupt() reads a packet of touch data from the device into a fixed-size on-stack buffer
struct mms114_touch touch[MMS114_MAX_TOUCH];
which holds MMS114_MAX_TOUCH (10) events of MMS114_EVENT_SIZE (8) bytes, i.e. 80 bytes. The length of the I2C read into it is taken verbatim from the device:
packet_size = mms114_read_reg(data, MMS114_PACKET_SIZE); if (packet_size <= 0) goto out; ... error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size, (u8 *)touch);
packet_size is a single device register byte (0x0F) and the only check is the lower bound packet_size <= 0; it is never bounded against the size of touch[]. A malfunctioning, malicious or counterfeit controller (or an attacker tampering with the I2C bus) can report a packet_size of up to 255, so __mms114_read_reg() writes up to 175 bytes past the end of touch[] on the IRQ-thread stack: a stack out-of-bounds write that can overwrite the stack canary, saved registers and the return address.
A well-formed device never reports more than the buffer holds, so reject an oversized packet and drop the report, consistent with the handler's other error paths, rather than reading past the buffer.
--- drivers/input/touchscreen/mms114.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/input/touchscreen/mms114.c +6 -0
@@ -236,6 +236,12 @@ static irqreturn_t mms114_interrupt(intif (packet_size <=0 ) goto out; +if (packet_size >sizeof (touch)) { +dev_err (&client->dev,"Invalid packet size %d (max %zu)\n" , + packet_size,sizeof (touch)); + goto out; + } +/* MMS136 has slightly different event size */ if (data->type ==TYPE_MMS134S || data->type ==TYPE_MMS136 ) event_size =MMS136_EVENT_SIZE ;
Greg Kroah-Hartman
maintainerPATCH 314/1266 Input: maplemouse - fix NULL pointer dereference in open()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Fuchs <[email protected]>
commit ee89db004238bd0b034f2a6176e175561658750b upstream.
Commit 555c765b0cc2 ("Input: mouse - drop unnecessary calls to input_set_drvdata") dropped the input_set_drvdata() call in probe because the data appeared to be unused. However, dc_mouse_open() and dc_mouse_close() were using maple_get_drvdata(to_maple_dev(&dev->dev)). This appears to be accessing the data attached to an instance of maple_device structure, while in reality this actually retrieves driver data from the input device's embedded struct device (doing invalid conversion of input device structure to maple device). After input_set_drvdata() was removed, that lookup started returning NULL and opening the input device dereferences mse->mdev.
Restore input_set_drvdata() and convert open() and close() to use input_get_drvdata() so the dependency is no longer hidden.
--- drivers/input/mouse/maplemouse.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/input/mouse/maplemouse.c +3 -2
@@ -48,7 +48,7 @@ static void dc_mouse_callback(struct mapstatic int dc_mouse_open (struct input_dev *dev) { -struct dc_mouse *mse =maple_get_drvdata (to_maple_dev (&dev->dev)); +struct dc_mouse *mse =input_get_drvdata (dev);maple_getcond_callback (mse->mdev, dc_mouse_callback,HZ /50 ,MAPLE_FUNC_MOUSE );
@@ -58,7 +58,7 @@ static int dc_mouse_open(struct input_destatic void dc_mouse_close (struct input_dev *dev) { -struct dc_mouse *mse =maple_get_drvdata (to_maple_dev (&dev->dev)); +struct dc_mouse *mse =input_get_drvdata (dev);maple_getcond_callback (mse->mdev, dc_mouse_callback,0 ,MAPLE_FUNC_MOUSE );
@@ -88,6 +88,7 @@ static int probe_maple_mouse(struct devi mse->dev = input_dev; mse->mdev = mdev; +input_set_drvdata (input_dev, mse); input_dev->evbit[0 ] =BIT_MASK (EV_KEY ) |BIT_MASK (EV_REL ); input_dev->keybit[BIT_WORD (BTN_MOUSE )] =BIT_MASK (BTN_LEFT ) |BIT_MASK (BTN_RIGHT ) |BIT_MASK (BTN_MIDDLE );
Greg Kroah-Hartman
maintainerPATCH 315/1266 Input: mms114 - fix multi-touch slot corruption
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit adea84ee6cdea611146c4251d3c1616f5a09feca upstream.
If the touchscreen controller reports a touch ID of 0, the driver calculates the slot ID as touch->id - 1, which underflows to UINT_MAX. This is passed to input_mt_slot() as -1.
Since the input core ignores negative slot values, the active slot remains unchanged. The driver then reports the touch coordinates for the previously active slot, corrupting its state.
Fix this by rejecting touch reports with ID 0.
--- drivers/input/touchscreen/mms114.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/touchscreen/mms114.c +1 -1
@@ -165,7 +165,7 @@ static void mms114_process_mt(struct mmsunsigned int x;unsigned int y; -if (touch->id >MMS114_MAX_TOUCH ) { +if (touch->id ==0 || touch->id >MMS114_MAX_TOUCH ) {dev_err (&client->dev,"Wrong touch id (%d)\n" , touch->id);return ; }
Greg Kroah-Hartman
maintainerPATCH 316/1266 Input: maple_keyb - set driver data before registering input device
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 536394ec81419b67d9f4f0028812c4372397be1b upstream.
Set maple driver data before calling input_register_device() to ensure that it is available if the device is opened immediately and the callback is triggered.
--- drivers/input/keyboard/maple_keyb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/input/keyboard/maple_keyb.c +2 -2
@@ -169,6 +169,8 @@ static int probe_maple_kbd(struct device kbd->dev = idev;memcpy (kbd->keycode, dc_kbd_keycode,sizeof (kbd->keycode)); +maple_set_drvdata (mdev, kbd); + idev->name = mdev->product_name; idev->evbit[0 ] =BIT (EV_KEY ) |BIT (EV_REP ); idev->keycode = kbd->keycode;
@@ -193,8 +195,6 @@ static int probe_maple_kbd(struct device mdev->driver = mdrv; -maple_set_drvdata (mdev, kbd); -return error; fail_register:
Greg Kroah-Hartman
maintainerPATCH 317/1266 Input: maplemouse - set driver data before registering input device
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 738f24bbbc95dd50cb4229d1ed62a05f29db2bda upstream.
Set maple driver data before calling input_register_device() to ensure that it is available if the device is opened immediately and the callback is triggered.
--- drivers/input/mouse/maplemouse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/input/mouse/maplemouse.c +3 -1
@@ -88,6 +88,8 @@ static int probe_maple_mouse(struct devi mse->dev = input_dev; mse->mdev = mdev; +maple_set_drvdata (mdev, mse); +input_set_drvdata (input_dev, mse); input_dev->evbit[0 ] =BIT_MASK (EV_KEY ) |BIT_MASK (EV_REL ); input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
@@ -103,12 +105,12 @@ static int probe_maple_mouse(struct devi goto fail_register; mdev->driver = mdrv; -maple_set_drvdata (mdev, mse);return error; fail_register:input_free_device (input_dev); +maple_set_drvdata (mdev,NULL ); fail_nomem:kfree (mse); fail:
Greg Kroah-Hartman
maintainerPATCH 318/1266 Input: maplecontrol - set driver data before registering input device
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit fe938ee497d58c644f6910cfe6ae155f6fb3e523 upstream.
Set maple driver data before calling input_register_device() to ensure that it is available if the device is opened immediately and the callback is triggered.
--- drivers/input/joystick/maplecontrol.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/input/joystick/maplecontrol.c +2 -1
@@ -112,6 +112,8 @@ static int probe_maple_controller(struct pad->dev = idev; pad->mdev = mdev; +maple_set_drvdata (mdev, pad); + idev->open = dc_pad_open; idev->close = dc_pad_close;
@@ -146,7 +148,6 @@ static int probe_maple_controller(struct goto fail; mdev->driver = mdrv; -maple_set_drvdata (mdev, pad);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 319/1266 RDMA/rtrs-srv: Bound RDMA-Write length to chunk size in rdma_write_sg
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhenhao Wan <[email protected]>
commit 963af8d97a8c6a117134a8d0db1415e0489200b1 upstream.
When the server answers an RTRS READ, rdma_write_sg() builds the source scatter/gather entry for the IB_WR_RDMA_WRITE that returns data to the peer. Its length is taken directly from the wire descriptor:
plist->length = le32_to_cpu(id->rd_msg->desc[0].len);
rd_msg points into the chunk buffer that the remote peer filled via RDMA-WRITE-WITH-IMM (rtrs_srv_rdma_done() -> process_io_req() -> process_read()), so desc[0].len is attacker-controlled and, before this change, was only rejected when zero. The source address is the fixed chunk start (dma_addr[msg_id]) and the source lkey is the PD-wide local_dma_lkey, which is not tied to the chunk's MR mapping, so the verbs layer does not constrain the transfer length to max_chunk_size. msg_id and off are bounded against queue_depth and max_chunk_size in rtrs_srv_rdma_done(), but desc[0].len is a separate field that was not checked against the chunk size.
A peer that advertises desc[0].len larger than max_chunk_size can make the posted RDMA write read past the chunk's mapped region. The resulting behaviour depends on the IOMMU configuration: with no IOMMU or in passthrough mode the read may extend into memory adjacent to the chunk and be returned to the peer, which can disclose host memory; with a translating IOMMU the out-of-range access is expected to fault and abort the connection. In either case the transfer exceeds what the protocol permits and is driven by a remote peer.
Reject a descriptor length above max_chunk_size, mirroring the existing off >= max_chunk_size bound in rtrs_srv_rdma_done(). Legitimate clients do not exceed it: the client sets desc[0].len to its MR length, which is capped at the negotiated max_io_size (max_chunk_size - MAX_HDR_SIZE).
--- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/infiniband/ulp/rtrs/rtrs-srv.c +3 -2
@@ -224,8 +224,9 @@ static int rdma_write_sg(struct rtrs_srv/* WR will fail with length error * if this is 0 */ -if (plist->length ==0 ) { -rtrs_err (s,"Invalid RDMA-Write sg list length 0\n" ); +if (plist->length ==0 || plist->length > max_chunk_size) { +rtrs_err (s,"Invalid RDMA-Write sg list length %u\n" , + plist->length);return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 320/1266 RDMA/siw: bound Read Response placement to the RREAD length
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 7d29f7e9dbd844cae4d3e559cf78324b9642fd6b upstream.
In drivers/infiniband/sw/siw/siw_qp_rx.c, siw_proc_rresp() places each inbound Read Response DDP segment at sge->laddr + wqe->processed and then accumulates wqe->processed, but it never checks the running total against the sink buffer length on continuation segments. siw_check_sge() resolves and validates the sink memory only on the first fragment (the if (!*mem) branch), and siw_rresp_check_ntoh() compares the cumulative length against wqe->bytes only on the final segment (the !frx->more_ddp_segs guard).
A connected siw peer that answers an outstanding RREAD with Read Response segments that keep the DDP Last flag clear, carrying more total payload than the RREAD requested, drives wqe->processed past the validated sink buffer; the next siw_rx_data() call writes out of bounds at sge->laddr + wqe->processed. siw runs iWARP over ordinary routable TCP, so the peer is the remote end of an established RDMA connection and needs no local privilege.
Bound every segment before placement, exactly as siw_proc_send() and siw_proc_write() already do for their tagged and untagged paths, and terminate the connection with a base-or-bounds DDP error when the Read Response would overrun the sink buffer.
This is the second receive-path length fix for this file. A separate change rejects an MPA FPDU length that underflows the per-fragment remainder in the header decode; that guard does not cover this case, because here each individual segment length is self-consistent and only the accumulated placement offset overruns the buffer.
--- drivers/infiniband/sw/siw/siw_qp_rx.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/infiniband/sw/siw/siw_qp_rx.c +9 -0
@@ -848,6 +848,15 @@ int siw_proc_rresp(struct siw_qp *qp) } mem_p = *mem; +if (unlikely (wqe->processed + srx->fpdu_part_rem > wqe->bytes)) { +siw_dbg_qp (qp,"rresp len: %d + %d > %d\n" , + wqe->processed, srx->fpdu_part_rem, wqe->bytes); + wqe->wc_status =SIW_WC_LOC_LEN_ERR ; +siw_init_terminate (qp,TERM_ERROR_LAYER_DDP , +DDP_ETYPE_TAGGED_BUF , +DDP_ECODE_T_BASE_BOUNDS ,0 ); +return -EINVAL ; + } bytes =min (srx->fpdu_part_rem, srx->skb_new);if (mem_p->mem_obj ==NULL )
Greg Kroah-Hartman
maintainerPATCH 321/1266 fuse: fix device node leak in cuse_process_init_reply()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alberto Ruiz <[email protected]>
commit 9fa4f7a53406430ee9982f2f636a15b338185122 upstream.
If device_add() succeeds during CUSE initialization but a subsequent step (cdev_alloc() or cdev_add()) fails, the error path calls put_device() without first calling device_del(). This leaks the devtmpfs entry created by device_add(), leaving a stale /dev/<name> node that persists until reboot.
Since the cuse_conn is never linked into cuse_conntbl on the failure path, cuse_channel_release() sees cc->dev == NULL and skips device_unregister(), so no other code path cleans up the node.
This has several consequences:
- The device name is permanently poisoned: any subsequent attempt to create a CUSE device with the same name hits the stale sysfs entry, device_add() fails, and the new device is aborted.
- The collision manifests as ENODEV returned to userspace with no dmesg diagnostic, making it very difficult to debug.
- The failure is self-perpetuating: once a name is leaked, all future attempts with that name fail identically.
Fix this by introducing an err_dev label that calls device_del() to undo device_add() before falling through to err_unlock. The existing err_unlock path from a device_add() failure correctly skips device_del() since the device was never added.
Testing instructions can be found at the lore link below.
--- fs/fuse/cuse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/fuse/cuse.c +3 -1
@@ -386,7 +386,7 @@ static void cuse_process_init_reply(stru rc = -ENOMEM ; cdev =cdev_alloc ();if (!cdev) - goto err_unlock; + goto err_dev; cdev->owner =THIS_MODULE ; cdev->ops = &cuse_frontend_fops;
@@ -412,6 +412,8 @@ out: err_cdev:cdev_del (cdev); +err_dev: +device_del (dev); err_unlock:mutex_unlock (&cuse_lock);put_device (dev);
Greg Kroah-Hartman
maintainerPATCH 322/1266 fuse: re-lock request before returning from fuse_ref_folio()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joanne Koong <[email protected]>
commit b5befa80fdbe287a98480effed9564712924add5 upstream.
fuse_ref_folio() unlocks the request but does not re-lock it before returning. fuse_chan_abort() can end the request and the async end callback (eg fuse_writepage_free()) can free the args while the subsequent copy chain logic after fuse_ref_folio() accesses them, leading to use-after-free issues.
Fix this by locking the request in fuse_ref_folio() before returning.
--- fs/fuse/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/fuse/dev.c +1 -1
@@ -912,7 +912,7 @@ static int fuse_ref_page(struct fuse_cop cs->nr_segs++; cs->len =0 ; -return 0 ; +return lock_request (cs->req); }/*
Greg Kroah-Hartman
maintainerPATCH 323/1266 smb: client: reject overlapping data areas in SMB2 responses
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shoichiro Miyamoto <[email protected]>
commit 8986c932905ea508d66da421eb2eb6e676ace1fe upstream.
Commit 53b7c271f06b ("smb: client: restrict implied bcc[0] exemption to responses without data area") restricted the implied bcc[0] length exception to responses without a data area. However, the overlap handling in __smb2_calc_size() clears data_length, which can make an invalid response appear to have no data area and so qualify for the exception.
Track data area overlap separately and reject such responses before applying the length compatibility exceptions.
--- fs/smb/client/smb2misc.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-)
fs/smb/client/smb2misc.c +25 -9
@@ -18,7 +18,8 @@#include "nterr.h" #include "cached_dir.h" -static unsigned int __smb2_calc_size (void *buf,bool *have_data); +static unsigned int __smb2_calc_size (void *buf,bool *have_data, +bool *data_area_overlap);static int check_smb2_hdr (struct smb2_hdr *shdr,__u64 mid)
@@ -146,6 +147,7 @@ smb2_check_message(char *buf, unsigned i__u32 calc_len;/* calculated length */ __u64 mid;bool have_data; +bool data_area_overlap;/* If server is a channel, select the primary channel */ pserver =SERVER_IS_CHAN (server) ? server->primary_server : server;
@@ -230,7 +232,12 @@ smb2_check_message(char *buf, unsigned i } have_data = false; - calc_len =__smb2_calc_size (buf, &have_data); + data_area_overlap = false; + calc_len =__smb2_calc_size (buf, &have_data, &data_area_overlap); + +/* Reject responses whose data area overlaps the fixed area. */ +if (data_area_overlap) +return 1 ;/* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might * be 0, and not a real miscalculation */
@@ -414,14 +421,15 @@ smb2_get_data_area_len(int *off, int *le }/* -* Calculate the size of the SMB message based on the fixed header -* portion, the number of word parameters and the data portion of the message. -* If have_data is non-NULL, it is set to true when a non-empty data area was -* found (data_length > 0), allowing callers to distinguish the implied bcc[0] -* case (no data area) from an overreported data length. +* Calculate the size of the SMB message based on the fixed header, fixed +* parameter area, and variable data area. +* +* If have_data is not NULL, it is set when a non-empty data area is found. +* If data_area_overlap is not NULL, it is set when the data area overlaps +* the fixed area. */ static unsigned int -__smb2_calc_size (void *buf,bool *have_data) +__smb2_calc_size (void *buf,bool *have_data,bool *data_area_overlap) {struct smb2_pdu *pdu = buf;struct smb2_hdr *shdr = &pdu->hdr;
@@ -430,6 +438,11 @@ __smb2_calc_size(void *buf, bool *have_d/* Structure Size has already been checked to make sure it is 64 */ int len =le16_to_cpu (shdr->StructureSize); +if (have_data) + *have_data = false; +if (data_area_overlap) + *data_area_overlap = false; +/* * StructureSize2, ie length of fixed parameter area has already * been checked to make sure it is the correct length.
@@ -452,7 +465,10 @@ __smb2_calc_size(void *buf, bool *have_dif (offset +1 < len) {cifs_dbg (VFS ,"data area offset %d overlaps SMB2 header %d\n" , offset +1 , len); +if (data_area_overlap) + *data_area_overlap = true; data_length =0 ; + goto calc_size_exit; }else { len = offset + data_length; }
@@ -467,7 +483,7 @@ calc_size_exit:unsigned int smb2_calc_size (void *buf) { -return __smb2_calc_size (buf,NULL ); +return __smb2_calc_size (buf,NULL ,NULL ); }/* Note: caller must free return buffer */
Greg Kroah-Hartman
maintainerPATCH 324/1266 xfs: fail recovery on a committed log item with no regions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
commit 2094dab19d45c487285617b7b68913d0cc0c1211 upstream.
If the first op of a transaction is a bare transaction header (len == sizeof(struct xfs_trans_header)), xlog_recover_add_to_trans() adds an item but no region, leaving it on r_itemq with ri_cnt == 0 and ri_buf == NULL.
The header can be split across op records, so later ops may still add regions; the item is only invalid if the transaction commits with none. The runtime commit path never emits such a transaction, so this only happens on a crafted log. It came from an AI-assisted code audit of the recovery parser.
xlog_recover_reorder_trans() calls ITEM_TYPE() on the item, which reads *(unsigned short *)item->ri_buf[0].iov_base and faults on the NULL ri_buf. Reject it there, before the commit handlers that also read ri_buf[0].
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] RIP: 0010:xlog_recover_reorder_trans (fs/xfs/xfs_log_recover.c:1836) xlog_recover_commit_trans (fs/xfs/xfs_log_recover.c:2043) xlog_recover_process_data (fs/xfs/xfs_log_recover.c:2501) xlog_do_recovery_pass (fs/xfs/xfs_log_recover.c:3244) xlog_recover (fs/xfs/xfs_log_recover.c:3493) xfs_log_mount (fs/xfs/xfs_log.c:618) xfs_mountfs (fs/xfs/xfs_mount.c:1034) xfs_fs_fill_super (fs/xfs/xfs_super.c:1938) vfs_get_tree (fs/super.c:1695) path_mount (fs/namespace.c:4161) __x64_sys_mount (fs/namespace.c:4367)
--- fs/xfs/xfs_log_recover.c | 9 +++++++++ 1 file changed, 9 insertions(+)
fs/xfs/xfs_log_recover.c +9 -0
@@ -1872,6 +1872,15 @@ xlog_recover_reorder_trans(list_for_each_entry_safe (item, n, &sort_list, ri_list) {enum xlog_recover_reorder fate =XLOG_REORDER_ITEM_LIST ; +/* a committed item with no regions has a NULL ri_buf[0] */ +if (!item->ri_cnt || !item->ri_buf) { +xfs_warn (log->l_mp, +"%s: committed log item has no regions" , + __func__); + error = -EFSCORRUPTED ; +break ; + } + item->ri_ops =xlog_find_item_ops (item);if (!item->ri_ops) { xfs_warn(log->l_mp,
Greg Kroah-Hartman
maintainerPATCH 325/1266 xfs: resample the data fork mapping after cycling ILOCK
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Darrick J. Wong <[email protected]>
commit 2f4acd0fcd862e22eab45690ec2c08c80b6ef2e7 upstream.
xfs_reflink_fill_{cow_hole,delalloc} are both presented with an inode, a data fork mapping, and a cow fork mapping. Unfortunately, these two helpers cycle the ILOCK to grab a transaction, which means that the mappings are stale as soon as we reacquire the ILOCK. Currently we refresh the cow fork mapping by re-calling xfs_find_trim_cow_extent, but we don't refresh the data fork mapping beforehand, which means that the xfs_bmap_trim_cow in that function queries the refcount btree about the wrong physical blocks and returns an inaccurate value in *shared.
If *shared is now false, the directio write proceeds with a stale data fork mapping. Fix this by querying the data fork mapping if the sequence counter changes across the ILOCK cycle.
--- fs/xfs/xfs_reflink.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
fs/xfs/xfs_reflink.c +36 -0
@@ -389,6 +389,7 @@ xfs_reflink_fill_cow_hole(struct xfs_trans *tp;xfs_filblks_t resaligned;xfs_extlen_t resblks; +unsigned int seq_before =READ_ONCE (ip->i_df.if_seq);int nimaps;int error;bool found;
@@ -407,6 +408,22 @@ xfs_reflink_fill_cow_hole( *lockmode =XFS_ILOCK_EXCL ; +/* +* The data fork mapping may have changed while we dropped the ILOCK +* (a racing O_DIRECT writer under IOLOCK_SHARED can complete a full +* CoW cycle including xfs_reflink_end_cow(), which remaps this offset +* and drops the refcount of the old shared block). Re-read it so the +* shared-status recheck below and the caller's in-place iomap both +* operate on the current mapping rather than a stale physical block. +*/ +if (seq_before !=READ_ONCE (ip->i_df.if_seq)) { + nimaps =1 ; + error =xfs_bmapi_read (ip, imap->br_startoff, + imap->br_blockcount, imap, &nimaps,0 ); +if (error) + goto out_trans_cancel; + } + error =xfs_find_trim_cow_extent (ip, imap, cmap, shared, &found);if (error || !*shared) goto out_trans_cancel;
@@ -453,6 +470,8 @@ xfs_reflink_fill_delalloc(bool found; do { + unsigned int seq_before = READ_ONCE(ip->i_df.if_seq); + xfs_iunlock(ip, *lockmode); *lockmode = 0;
@@ -463,6 +482,23 @@ xfs_reflink_fill_delalloc( *lockmode =XFS_ILOCK_EXCL ; +/* +* The data fork mapping may have changed while we dropped the +* ILOCK (a racing O_DIRECT writer under IOLOCK_SHARED can +* complete a full CoW cycle including xfs_reflink_end_cow(), +* which remaps this offset and drops the refcount of the old +* shared block). Re-read it so the shared-status recheck +* below and the caller's in-place iomap both operate on the +* current mapping rather than a stale physical block. +*/ +if (seq_before !=READ_ONCE (ip->i_df.if_seq)) { + nimaps =1 ; + error =xfs_bmapi_read (ip, imap->br_startoff, + imap->br_blockcount, imap, &nimaps,0 ); +if (error) + goto out_trans_cancel; + } + error =xfs_find_trim_cow_extent (ip, imap, cmap, shared, &found);if (error || !*shared)
Greg Kroah-Hartman
maintainerPATCH 326/1266 smb/server: do not require delete access for non-replacing links
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: ChenXiaoSong <[email protected]>
[ Upstream commit 851ed9e09639e0daf79a506ce26097b296ed5518 ]
Reproducer:
1. server: systemctl start ksmbd
2. client: mount -t cifs //${server_ip}/export /mnt
3. client: touch /mnt/file; ln /mnt/file /mnt/hardlink
4. client err log: ln: failed to create hard link 'hardlink' => 'file': Permission denied
5. server err log: ksmbd: no right to delete : 0x80
--- fs/smb/server/smb2pdu.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
fs/smb/server/smb2pdu.c +8 -6
@@ -6504,16 +6504,18 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, }case FILE_LINK_INFORMATION : { -if (!(fp->daccess &FILE_DELETE_LE )) { -pr_err ("no right to delete : 0x%x\n" , fp->daccess); -return -EACCES ; - } +struct smb2_file_link_info *file_info;if (buf_len <sizeof (struct smb2_file_link_info ))return -EINVAL ; -return smb2_create_link (work, work->tcon->share_conf, - (struct smb2_file_link_info *)buffer, + file_info = (struct smb2_file_link_info *)buffer; +if (file_info->ReplaceIfExists && !(fp->daccess &FILE_DELETE_LE )) { +pr_err ("no right to delete : 0x%x\n" , fp->daccess); +return -EACCES ; + } + +return smb2_create_link (work, work->tcon->share_conf, file_info, buf_len, fp->filp, work->conn->local_nls); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 327/1266 block: skip sync_blockdev() on surprise removal in bdev_mark_dead()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Shi <[email protected]>
commit 49f06cff50a4ccf3b7a1a662ceb892b3b21a527a upstream.
bdev_mark_dead()'s @surprise == true means the device is already gone. The filesystem callback fs_bdev_mark_dead() honours this and skips sync_filesystem(), but the bare block device path (no ->mark_dead op) lost its !surprise guard when the holder ->mark_dead callback was wired up (see Fixes), and now calls sync_blockdev() unconditionally, which can hang forever waiting on writeback that can no longer complete.
syzkaller hit this via nvme_reset_work()'s "I/O queues lost" path:nvme_mark_namespaces_dead() -> blk_mark_disk_dead() -> bdev_mark_dead(bdev, true) -> sync_blockdev() blocks in folio_wait_writeback(), wedging the reset worker and every task waiting on it.
Skip the sync on surprise removal, matching fs_bdev_mark_dead(); invalidate_bdev() still runs. Orderly removal (surprise == false) is unchanged.
Found by FuzzNvme.
[ adjusted for 6.6.y: bdev_mark_dead() there still unlocks bd_holder_lock
after the if/else and the else arm is a bare sync_blockdev(), so the !surprise guard is added as "else if (!surprise)" instead of inside the mainline else block. ]
--- block/bdev.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
block/bdev.c +6 -1
@@ -1024,7 +1024,12 @@ void bdev_mark_dead(struct block_device *bdev, bool surprise)mutex_lock (&bdev->bd_holder_lock);if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead) bdev->bd_holder_ops->mark_dead (bdev, surprise); -else +/* +* On surprise removal the device is already gone; syncing is +* futile and can hang forever waiting on I/O that will never +* complete. Match fs_bdev_mark_dead(), which also skips it. +*/ +else if (!surprise)sync_blockdev (bdev);mutex_unlock (&bdev->bd_holder_lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 328/1266 sched/fair: Only update stats for allowed CPUs when looking for dst group
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adam Li <[email protected]>
[ Upstream commit 82d6e01a0699800efd8b048eb584c907ccb47b7a ]
Load imbalance is observed when the workload frequently forks new threads. Due to CPU affinity, the workload can run on CPU 0-7 in the first group, and only on CPU 8-11 in the second group. CPU 12-15 are always idle.
{ 0 1 2 3 4 5 6 7 } {8 9 10 11 12 13 14 15}
* * * * * * * * * * * *
When looking for dst group for newly forked threads, in many times update_sg_wakeup_stats() reports the second group has more idle CPUs than the first group. The scheduler thinks the second group is less busy. Then it selects least busy CPUs among CPU 8-11. Therefore CPU 8-11 can be crowded with newly forked threads, at the same time CPU 0-7 can be idle.
A task may not use all the CPUs in a schedule group due to CPU affinity. Only update schedule group statistics for allowed CPUs.
--- kernel/sched/fair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/fair.c +1 -1
@@ -10266,7 +10266,7 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd,if (sd->flags &SD_ASYM_CPUCAPACITY ) sgs->group_misfit_task_load =1 ; -for_each_cpu (i,sched_group_span (group)) { +for_each_cpu_and (i,sched_group_span (group), p->cpus_ptr) {struct rq *rq =cpu_rq (i);unsigned int local;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 329/1266 crypto: algif_skcipher - force synchronous processing on trees without ctx->state
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammet Kaan KILINÇ <[email protected]>
The AIO/async path in skcipher_recvmsg() passes the socket-wide ctx->iv directly into the skcipher request. After io_submit() the socket lock is dropped and the request is processed asynchronously, so a concurrent sendmsg(ALG_SET_IV) can overwrite ctx->iv and make the in-flight request run under an attacker-controlled IV. For CTR/stream modes this is IV/keystream reuse and lets an unprivileged user recover the plaintext of a concurrent operation.
Snapshotting ctx->iv into per-request storage for the async path is not sufficient. For ciphers with statesize == 0 - which includes cbc and ctr - the MSG_MORE inter-chunk IV chaining is carried solely by the in-place req->iv writeback, which a snapshot redirects into per-request memory that af_alg_free_resources() releases on completion, silently producing wrong output. Writing the IV back from the completion callback instead is not possible either: that would require lock_sock() there, but the callback can run in softirq/atomic context, so it must not sleep.
Make the operation synchronous instead, which removes both the IV race and any writeback race. This is equivalent to the upstream resolution, commit fcc77d33a34c ("net: Remove support for AIO on sockets"), which removed the AIO socket path across net/ entirely and so produces the same end state for this file. This patch deviates from that commit deliberately: rather than removing AIO socket support tree-wide, which would be far too invasive for stable, it removes only the AIO branch in crypto/algif_skcipher.c. io_submit() now completes synchronously; AF_ALG async is rarely used in practice.
The -EIOCBQUEUED check in skcipher_recvmsg() is now dead but harmless, and is left alone to keep the fix minimal.
Tested on 6.6.y: attacker IV injection dropped from 2296/200000 to 0/200000 after the change; MSG_MORE chunked CTR output bit-identical to single-shot.
--- crypto/algif_skcipher.c | 49 +++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 31 deletions(-)
crypto/algif_skcipher.c +18 -31
@@ -107,37 +107,24 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,skcipher_request_set_crypt (&areq->cra_u.skcipher_req, areq->tsgl, areq->first_rsgl.sgl.sgt.sgl, len, ctx->iv); -if (msg->msg_iocb && !is_sync_kiocb (msg->msg_iocb)) { -/* AIO operation */ -sock_hold (sk); - areq->iocb = msg->msg_iocb; - -/* Remember output size that will be generated. */ - areq->outlen = len; - -skcipher_request_set_callback (&areq->cra_u.skcipher_req, -CRYPTO_TFM_REQ_MAY_SLEEP , - af_alg_async_cb, areq); - err = ctx->enc ? -crypto_skcipher_encrypt (&areq->cra_u.skcipher_req) : -crypto_skcipher_decrypt (&areq->cra_u.skcipher_req); - -/* AIO operation in progress */ -if (err == -EINPROGRESS ) -return -EIOCBQUEUED ; - -sock_put (sk); - }else { -/* Synchronous operation */ -skcipher_request_set_callback (&areq->cra_u.skcipher_req, -CRYPTO_TFM_REQ_MAY_SLEEP | -CRYPTO_TFM_REQ_MAY_BACKLOG , - crypto_req_done, &ctx->wait); - err =crypto_wait_req (ctx->enc ? -crypto_skcipher_encrypt (&areq->cra_u.skcipher_req) : -crypto_skcipher_decrypt (&areq->cra_u.skcipher_req), - &ctx->wait); - } +/* +* Force synchronous processing. The async (AIO) path passed the +* socket-wide ctx->iv into the request, which the worker +* dereferenced after the socket lock was dropped, letting a +* concurrent sendmsg(ALG_SET_IV) inject an attacker IV. Mainline +* removed the AIO socket path in commit fcc77d33a34c ("net: Remove +* support for AIO on sockets"); these stable trees lack the +* per-request ctx->state used by newer kernels, so the minimal safe +* fix is to always complete synchronously. +*/ +skcipher_request_set_callback (&areq->cra_u.skcipher_req, +CRYPTO_TFM_REQ_MAY_SLEEP | +CRYPTO_TFM_REQ_MAY_BACKLOG , + crypto_req_done, &ctx->wait); + err =crypto_wait_req (ctx->enc ? +crypto_skcipher_encrypt (&areq->cra_u.skcipher_req) : +crypto_skcipher_decrypt (&areq->cra_u.skcipher_req), + &ctx->wait); free:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 330/1266 KVM: arm64: Bound used_lrs when flushing the pKVM hyp vCPU
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
commit 8cc8bbbfab14c22c5551d0dd19b208a44b141c76 upstream.
flush_hyp_vcpu() copies the host vGIC state into the hyp's private vCPU on every run. The vGIC list register save and restore use used_lrs as their loop bound and expect it to stay within the number of implemented list registers. While this is generally the case, flush_hyp_vcpu() copies vgic_v3 verbatim and does not enforce this, so a value provided by the host is used at EL2 to index vgic_lr[] and access ICH_LR<n>_EL2 (host -> EL2).
Fix by clamping used_lrs to the number of implemented list registers after the copy, as the trusted path already does in vgic_flush_lr_state(). The number of implemented list registers is constant after init, so it is replicated once from kvm_vgic_global_state.nr_lr into hyp_gicv3_nr_lr rather than read on every entry.
--- arch/arm64/include/asm/kvm_hyp.h | 1 + arch/arm64/kvm/arm.c | 2 ++ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 9 +++++++++ 3 files changed, 12 insertions(+)
arch/arm64/include/asm/kvm_hyp.h +1 -0
@@ -146,5 +146,6 @@ extern u64 kvm_nvhe_sym(id_aa64smfr0_el1_sys_val);extern unsigned long kvm_nvhe_sym (__icache_flags );extern unsigned int kvm_nvhe_sym (kvm_arm_vmid_bits );extern unsigned int kvm_nvhe_sym (kvm_host_sve_max_vl ); +extern unsigned int kvm_nvhe_sym (hyp_gicv3_nr_lr );#endif /* __ARM64_KVM_HYP_H__ */
arch/arm64/kvm/arm.c +2 -0
@@ -2026,6 +2026,8 @@ static int __init init_subsystems(void)switch (err) {case 0 : vgic_present = true; +if (static_branch_unlikely (&kvm_vgic_global_state.gicv3_cpuif)) +kvm_nvhe_sym (hyp_gicv3_nr_lr) = kvm_vgic_global_state.nr_lr;break ;case -ENODEV :case -ENXIO :
arch/arm64/kvm/hyp/nvhe/hyp-main.c +9 -0
@@ -22,6 +22,9 @@ DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); +/* Number of implemented GICv3 LRs. Used by flush_hyp_vcpu(). */ +unsigned int hyp_gicv3_nr_lr; +void __kvm_hyp_host_forward_smc (struct kvm_cpu_context *host_ctxt);static void flush_hyp_vcpu (struct pkvm_hyp_vcpu *hyp_vcpu)
@@ -46,6 +49,12 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) hyp_vcpu->vcpu.arch.vsesr_el2 = host_vcpu->arch.vsesr_el2; hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3; + +/* Bound used_lrs by the number of implemented list registers. */ + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs = + min_t(unsigned int, + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs, + hyp_gicv3_nr_lr); }static void sync_hyp_vcpu (struct pkvm_hyp_vcpu *hyp_vcpu)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 331/1266 KVM: arm64: Clear __hyp_running_vcpu when flushing the pKVM hyp vCPU
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
commit e8042f6e1d7befb2fb6b10a75918642bcd0acf9a upstream.
flush_hyp_vcpu() copies the host vCPU context into the hyp's private vCPU on every run. ctxt_to_vcpu() expects a guest context to have a NULL __hyp_running_vcpu, which is only ever set on the host context, so that it resolves the vCPU via container_of(). While this is generally the case, flush_hyp_vcpu() copies the context verbatim and does not enforce this, so a value provided by the host is dereferenced at EL2 (host -> EL2).
Fix by clearing __hyp_running_vcpu after the copy.
--- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 3 +++ 1 file changed, 3 insertions(+)
arch/arm64/kvm/hyp/nvhe/hyp-main.c +3 -0
@@ -33,6 +33,9 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt; +/* __hyp_running_vcpu must be NULL in a guest context. */ + hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu =NULL ; + hyp_vcpu->vcpu.arch.sve_state =kern_hyp_va (host_vcpu->arch.sve_state); hyp_vcpu->vcpu.arch.sve_max_vl = host_vcpu->arch.sve_max_vl;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 332/1266 nvmet-tcp: check INIT_FAILED before nvmet_req_uninit in digest error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shivam Kumar <[email protected]>
commit 4606467a75cfc16721937272ed29462a750b60c8 upstream.
In nvmet_tcp_try_recv_ddgst(), when a data digest mismatch is detected, nvmet_req_uninit() is called unconditionally. However, if the command arrived via the nvmet_tcp_handle_req_failure() path, nvmet_req_init() had returned false and percpu_ref_tryget_live() was never executed. The unconditional percpu_ref_put() inside nvmet_req_uninit() then causes a refcount underflow, leading to a WARNING in percpu_ref_switch_to_atomic_rcu, a use-after-free diagnostic, and eventually a permanent workqueue deadlock.
Check cmd->flags & NVMET_TCP_F_INIT_FAILED before calling nvmet_req_uninit(), matching the existing pattern in nvmet_tcp_execute_request().
--- drivers/nvme/target/tcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/nvme/target/tcp.c +2 -1
@@ -1297,7 +1297,8 @@ static int nvmet_tcp_try_recv_ddgst(stru queue->idx, cmd->req.cmd->common.command_id, queue->pdu.cmd.hdr.type,le32_to_cpu (cmd->recv_ddgst), le32_to_cpu(cmd->exp_ddgst)); -nvmet_req_uninit (&cmd->req); +if (!(cmd->flags &NVMET_TCP_F_INIT_FAILED )) +nvmet_req_uninit (&cmd->req);nvmet_tcp_free_cmd_buffers (cmd);nvmet_tcp_fatal_error (queue); ret = -EPROTO ;
Greg Kroah-Hartman
maintainerPATCH 333/1266 nvmet-tcp: Fix potential UAF when ddgst mismatch
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sagi Grimberg <[email protected]>
commit dbbd07d0a7020b80f6a7028e561908f7b83b3d5a upstream.
Shivam Kumar found via vulnerability testing:
When data digest is enabled on an NVMe/TCP connection and a digest mismatch occurs on a non-final H2C_DATA PDU during an R2T-based data transfer, the digest error handler in nvmet_tcp_try_recv_ddgst() calls nvmet_req_uninit() — which performs percpu_ref_put() on the submission queue — but does NOT mark the command as completed. It does not set cqe->status, does not modify rbytes_done, and does not clear any flag. When the subsequent fatal error triggers queue teardown, nvmet_tcp_uninit_data_in_cmds() iterates all commands, checks nvmet_tcp_need_data_in() for each one, and finds that the already-uninited command still appears to need data (because rbytes_done < transfer_len and cqe->status == 0). It therefore calls nvmet_req_uninit() a second time on the same command — a double percpu_ref_put against a single percpu_ref_get.
--- drivers/nvme/target/tcp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/nvme/target/tcp.c +3 -1
@@ -1297,8 +1297,10 @@ static int nvmet_tcp_try_recv_ddgst(stru queue->idx, cmd->req.cmd->common.command_id, queue->pdu.cmd.hdr.type,le32_to_cpu (cmd->recv_ddgst), le32_to_cpu(cmd->exp_ddgst)); -if (!(cmd->flags &NVMET_TCP_F_INIT_FAILED )) +if (!(cmd->flags &NVMET_TCP_F_INIT_FAILED )) { + cmd->req.cqe->status =NVME_SC_CMD_SEQ_ERROR ;nvmet_req_uninit (&cmd->req); + }nvmet_tcp_free_cmd_buffers (cmd);nvmet_tcp_fatal_error (queue); ret = -EPROTO ;
Greg Kroah-Hartman
maintainerPATCH 334/1266 crypto: sun4i-ss - Remove insecure and unused rng_alg
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit b2c41fa9dd8fc740c489e060b199165771f268d1 upstream.
Remove sun4i_ss_rng, as it is insecure and unused:
- It has multiple vulnerabilities. sun4i_ss_prng_seed() is missing locking and has a buffer overflow. sun4i_ss_prng_generate() fails to fill the entire buffer with cryptographic random bytes, because it rounds the destination length down and also doesn't actually wait for the hardware to be ready before pulling bytes from it.
- No user of this code is known. It's usable only theoretically via the "rng" algorithm type of AF_ALG. But userspace actually just uses the actual Linux RNG (/dev/random etc) instead. And rng_algs don't contribute entropy to the actual Linux RNG either. (This may have been confused with hwrng, which does contribute entropy.)
The sun4i_ss_prng_seed() buffer overflow was reported by Tianchu Chen and discovered by Atuin - Automated Vulnerability Discovery Engine
There's no point in fixing all these vulnerabilities individually when this is unused code, so let's just remove it.
--- arch/arm/configs/sunxi_defconfig | 1 - drivers/crypto/allwinner/Kconfig | 8 --- drivers/crypto/allwinner/sun4i-ss/Makefile | 1 - .../crypto/allwinner/sun4i-ss/sun4i-ss-core.c | 36 ---------- .../crypto/allwinner/sun4i-ss/sun4i-ss-prng.c | 69 ------------------- drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 20 ------ 6 files changed, 135 deletions(-) delete mode 100644 drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c
arch/arm/configs/sunxi_defconfig +0 -1
@@ -170,7 +170,6 @@ CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_CRYPTO_DEV_SUN4I_SS=y -CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG=y CONFIG_CRYPTO_DEV_SUN8I_CE=y CONFIG_CRYPTO_DEV_SUN8I_SS=y CONFIG_DMA_CMA=y
drivers/crypto/allwinner/Kconfig +0 -8
@@ -24,14 +24,6 @@ config CRYPTO_DEV_SUN4I_SS To compile this driver as a module, choose M here: the module will be called sun4i-ss. -config CRYPTO_DEV_SUN4I_SS_PRNG - bool "Support for Allwinner Security System PRNG" - depends on CRYPTO_DEV_SUN4I_SS - select CRYPTO_RNG - help - Select this option if you want to provide kernel-side support for - the Pseudo-Random Number Generator found in the Security System. - config CRYPTO_DEV_SUN4I_SS_DEBUG bool "Enable sun4i-ss stats" depends on CRYPTO_DEV_SUN4I_SS
drivers/crypto/allwinner/sun4i-ss/Makefile +0 -1
@@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o -sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-prng.o
drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c +0 -36
@@ -215,23 +215,6 @@ static struct sun4i_ss_alg_template ss_algs[] = { } } }, -#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG -{ - .type = CRYPTO_ALG_TYPE_RNG, - .alg.rng = { - .base = { - .cra_name = "stdrng", - .cra_driver_name = "sun4i_ss_rng", - .cra_priority = 300, - .cra_ctxsize = 0, - .cra_module = THIS_MODULE, - }, - .generate = sun4i_ss_prng_generate, - .seed = sun4i_ss_prng_seed, - .seedsize = SS_SEED_LEN / BITS_PER_BYTE, - } -}, -#endif };static int sun4i_ss_debugfs_show (struct seq_file *seq,void *v)
@@ -249,12 +232,6 @@ static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v) ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb, ss_algs[i].stat_bytes);break ; -case CRYPTO_ALG_TYPE_RNG : -seq_printf (seq,"%s %s reqs=%lu tsize=%lu\n" , - ss_algs[i].alg.rng.base.cra_driver_name, - ss_algs[i].alg.rng.base.cra_name, - ss_algs[i].stat_req, ss_algs[i].stat_bytes); -break ;case CRYPTO_ALG_TYPE_AHASH : seq_printf(seq, "%s %s reqs=%lu\n", ss_algs[i].alg.hash.halg.base.cra_driver_name,
@@ -473,13 +450,6 @@ static int sun4i_ss_probe(struct platform_device *pdev) goto error_alg; }break ; -case CRYPTO_ALG_TYPE_RNG : - err =crypto_register_rng (&ss_algs[i].alg.rng); -if (err) { -dev_err (ss->dev,"Fail to register %s\n" , - ss_algs[i].alg.rng.base.cra_name); - } -break ; } }
@@ -499,9 +469,6 @@ static int sun4i_ss_probe(struct platform_device *pdev)case CRYPTO_ALG_TYPE_AHASH :crypto_unregister_ahash (&ss_algs[i].alg.hash);break ; -case CRYPTO_ALG_TYPE_RNG : -crypto_unregister_rng (&ss_algs[i].alg.rng); -break ; } } error_pm:
@@ -522,9 +489,6 @@ static int sun4i_ss_remove(struct platform_device *pdev)case CRYPTO_ALG_TYPE_AHASH :crypto_unregister_ahash (&ss_algs[i].alg.hash);break ; -case CRYPTO_ALG_TYPE_RNG : -crypto_unregister_rng (&ss_algs[i].alg.rng); -break ; } }
drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c deleted +0 -69
69 lines not on this page · raw message
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h +0 -20
@@ -31,8 +31,6 @@#include <crypto/internal/skcipher.h> #include <crypto/aes.h> #include <crypto/internal/des.h> -#include <crypto/internal/rng.h> -#include <crypto/rng.h> #define SS_CTL 0x00#define SS_KEY0 0x04
@@ -62,10 +60,6 @@/* SS_CTL configuration values */ -/* PRNG generator mode - bit 15 */ -#define SS_PRNG_ONESHOT (0 << 15) -#define SS_PRNG_CONTINUE (1 << 15) -/* IV mode for hash */ #define SS_IV_ARBITRARY (1 << 14)
@@ -94,14 +88,10 @@#define SS_OP_3DES (2 << 4)#define SS_OP_SHA1 (3 << 4)#define SS_OP_MD5 (4 << 4) -#define SS_OP_PRNG (5 << 4)/* Data end bit - bit 2 */ #define SS_DATA_END (1 << 2) -/* PRNG start bit - bit 1 */ -#define SS_PRNG_START (1 << 1) -/* SS Enable bit - bit 0 */ #define SS_DISABLED (0 << 0)#define SS_ENABLED (1 << 0)
@@ -128,9 +118,6 @@#define SS_RXFIFO_EMP_INT_ENABLE (1 << 2)#define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) -#define SS_SEED_LEN 192 -#define SS_DATA_LEN 160 -/* * struct ss_variant - Describe SS hardware variant * @sha1_in_be: The SHA1 digest is given by SS in BE, and so need to be inverted.
@@ -151,9 +138,6 @@ struct sun4i_ss_ctx {char buf[4 *SS_RX_MAX ];/* buffer for linearize SG src */ char bufo[4 *SS_TX_MAX ];/* buffer for linearize SG dst */ spinlock_t slock;/* control the use of the device */ -#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG -u32 seed[SS_SEED_LEN /BITS_PER_LONG ]; -#endif struct dentry *dbgfs_dir;struct dentry *dbgfs_stats; };
@@ -164,7 +148,6 @@ struct sun4i_ss_alg_template {union {struct skcipher_alg crypto;struct ahash_alg hash; -struct rng_alg rng; } alg;struct sun4i_ss_ctx *ss;unsigned long stat_req;
@@ -231,6 +214,3 @@ int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen);int sun4i_ss_des3_setkey (struct crypto_skcipher *tfm,const u8 *key,unsigned int keylen); -int sun4i_ss_prng_generate (struct crypto_rng *tfm,const u8 *src, -unsigned int slen,u8 *dst,unsigned int dlen); -int sun4i_ss_prng_seed (struct crypto_rng *tfm,const u8 *seed,unsigned int slen);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 335/1266 x86/mm: Fix check/use ordering in switch_mm_irqs_off()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Dolan <[email protected]>
This is a stable-specific fix. There is no single upstream commit to cherry-pick; the equivalent mainline fix is commit 83b0177a6c48 ("x86/mm: Fix SMP ordering in switch_mm_irqs_off()"), which is in v6.18 but does not apply to these trees because the surrounding code was refactored.
The backports of commit fea4e317f9e7 ("x86/mm: Eliminate window where TLB flushes may be inadvertently skipped") -- the fix for CVE-2025-37964 -- to the 6.1, 6.6 and 6.12 trees ended up with two code blocks in the wrong order relative to mainline. The fix depends on setting cpu_tlbstate.loaded_mm to LOADED_MM_SWITCHING *before* reading tlb_gen, so that a concurrent TLB shootdown either sees LOADED_MM_SWITCHING and sends the IPI, or the switching CPU sees the updated tlb_gen. In the stable trees the write of LOADED_MM_SWITCHING was placed after the tlb_gen read, so the race window fea4e317f9e7 was meant to close is still open and CVE-2025-37964 is unfixed there:
a process can be left running with stale TLB entries, which typically manifests as rare, hard-to-bisect memory corruption or segfaults.
This has been confirmed by several independent parties:
- reproduced on 6.1.y/6.6.y/6.12.y with the test program in [1], and confirmed fixed by this patch
- Seth Forshee saw segfaults on 6.12.y within ~30 minutes of running a test workload; with this patch it ran 18 hours cleanly [2]
- Greg Thelen reports 6.6.y- and 6.12.y-based test failures fixed by this patch [3]
Dave Hansen acked the patch [4] and has no objection to it going into stable [5].
The patch below is against 6.12.y; the identical change applies to 6.1.y and 6.6.y. (The cpumask_test_cpu()/smp_mb() portion of the mainline fix is not needed here because commit 209954cbc7d0 ("x86/mm/tlb: Update mm_cpumask lazily") was never backported to these trees.)
[1] https://lore.kernel.org/lkml/CAHDw0oGd0B4=uuv8NGqbUQ_ZVmSheU2bN70e4QhFXWvuAZdt2w@mail.gmail.com/
[2] https://lore.kernel.org/lkml/aZYWXe739XUJrBld@do-x1carbon/
[3] https://lore.kernel.org/lkml/CAHH2K0brx9omC9QYyB6Lio3t_1Lf8v=VaFoiaG23UgQ-aec89Q@mail.gmail.com/
[4] https://lore.kernel.org/lkml/[email protected]/
[5] https://lore.kernel.org/lkml/[email protected]/
--- arch/x86/mm/tlb.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
arch/x86/mm/tlb.c +8 -8
@@ -612,6 +612,14 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,*/ cond_mitigation (tsk); +/* +* Indicate that CR3 is about to change. nmi_uaccess_okay() +* and others are sensitive to the window where mm_cpumask(), +* CR3 and cpu_tlbstate.loaded_mm are not all in sync. +*/ +this_cpu_write (cpu_tlbstate.loaded_mm,LOADED_MM_SWITCHING ); +barrier (); +/* * Stop remote flushes for the previous mm. * Skip kernel threads; we never send init_mm TLB flushing IPIs,
@@ -629,14 +637,6 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, next_tlb_gen =atomic64_read (&next->context.tlb_gen);choose_new_asid (next, next_tlb_gen, &new_asid, &need_flush); - -/* -* Indicate that CR3 is about to change. nmi_uaccess_okay() -* and others are sensitive to the window where mm_cpumask(), -* CR3 and cpu_tlbstate.loaded_mm are not all in sync. -*/ -this_cpu_write (cpu_tlbstate.loaded_mm,LOADED_MM_SWITCHING ); -barrier (); } new_lam =mm_lam_cr3_mask (next);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 336/1266 crypto: crypto4xx - Remove ahash-related code
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
commit 97855e7f1ccf4917f305baab199edb9f2595ff5b upstream.
The hash implementation in crypto4xx has been disabled since 2009. As nobody has tried to fix this remove all the dead code.
--- drivers/crypto/amcc/crypto4xx_alg.c | 106 --------------------------- drivers/crypto/amcc/crypto4xx_core.c | 43 +---------- drivers/crypto/amcc/crypto4xx_core.h | 7 -- 3 files changed, 1 insertion(+), 155 deletions(-)
drivers/crypto/amcc/crypto4xx_alg.c +0 -106
@@ -12,9 +12,6 @@#include <linux/interrupt.h> #include <linux/spinlock_types.h> #include <linux/scatterlist.h> -#include <linux/crypto.h> -#include <linux/hash.h> -#include <crypto/internal/hash.h> #include <linux/dma-mapping.h> #include <crypto/algapi.h> #include <crypto/aead.h>
@@ -616,106 +613,3 @@ int crypto4xx_decrypt_aes_gcm(struct aead_request *req) {return crypto4xx_crypt_aes_gcm (req, true); } - -/* -* HASH SHA1 Functions -*/ -static int crypto4xx_hash_alg_init (struct crypto_tfm *tfm, -unsigned int sa_len, -unsigned char ha, -unsigned char hm) -{ -struct crypto_alg *alg = tfm->__crt_alg; -struct crypto4xx_alg *my_alg; -struct crypto4xx_ctx *ctx =crypto_tfm_ctx (tfm); -struct dynamic_sa_hash160 *sa; -int rc; - - my_alg = container_of(__crypto_ahash_alg(alg), struct crypto4xx_alg, - alg.u.hash); - ctx->dev = my_alg->dev; - -/* Create SA */ -if (ctx->sa_in || ctx->sa_out) -crypto4xx_free_sa (ctx); - - rc =crypto4xx_alloc_sa (ctx, sa_len); -if (rc) -return rc; - -crypto_ahash_set_reqsize (__crypto_ahash_cast (tfm), -sizeof (struct crypto4xx_ctx )); - sa = (struct dynamic_sa_hash160 *)ctx->sa_in; -set_dynamic_sa_command_0 (&sa->ctrl,SA_SAVE_HASH ,SA_NOT_SAVE_IV , -SA_NOT_LOAD_HASH ,SA_LOAD_IV_FROM_SA , -SA_NO_HEADER_PROC , ha,SA_CIPHER_ALG_NULL , -SA_PAD_TYPE_ZERO ,SA_OP_GROUP_BASIC , -SA_OPCODE_HASH ,DIR_INBOUND ); -set_dynamic_sa_command_1 (&sa->ctrl,0 ,SA_HASH_MODE_HASH , -CRYPTO_FEEDBACK_MODE_NO_FB ,SA_EXTENDED_SN_OFF , -SA_SEQ_MASK_OFF ,SA_MC_ENABLE , -SA_NOT_COPY_PAD ,SA_NOT_COPY_PAYLOAD , -SA_NOT_COPY_HDR ); -/* Need to zero hash digest in SA */ -memset (sa->inner_digest,0 ,sizeof (sa->inner_digest)); -memset (sa->outer_digest,0 ,sizeof (sa->outer_digest)); - -return 0 ; -} - -int crypto4xx_hash_init (struct ahash_request *req) -{ -struct crypto4xx_ctx *ctx =crypto_tfm_ctx (req->base.tfm); -int ds; -struct dynamic_sa_ctl *sa; - - sa = ctx->sa_in; - ds =crypto_ahash_digestsize ( -__crypto_ahash_cast (req->base.tfm)); - sa->sa_command_0.bf.digest_len = ds >>2 ; - sa->sa_command_0.bf.load_hash_state =SA_LOAD_HASH_FROM_SA ; - -return 0 ; -} - -int crypto4xx_hash_update (struct ahash_request *req) -{ -struct crypto_ahash *ahash =crypto_ahash_reqtfm (req); -struct crypto4xx_ctx *ctx =crypto_tfm_ctx (req->base.tfm); -struct scatterlist dst; -unsigned int ds =crypto_ahash_digestsize (ahash); - -sg_init_one (&dst, req->result, ds); - -return crypto4xx_build_pd (&req->base, ctx, req->src, &dst, - req->nbytes,NULL ,0 , ctx->sa_in, - ctx->sa_len,0 ,NULL ); -} - -int crypto4xx_hash_final (struct ahash_request *req) -{ -return 0 ; -} - -int crypto4xx_hash_digest (struct ahash_request *req) -{ -struct crypto_ahash *ahash =crypto_ahash_reqtfm (req); -struct crypto4xx_ctx *ctx =crypto_tfm_ctx (req->base.tfm); -struct scatterlist dst; -unsigned int ds =crypto_ahash_digestsize (ahash); - -sg_init_one (&dst, req->result, ds); - -return crypto4xx_build_pd (&req->base, ctx, req->src, &dst, - req->nbytes,NULL ,0 , ctx->sa_in, - ctx->sa_len,0 ,NULL ); -} - -/* -* SHA1 Algorithm -*/ -int crypto4xx_sha1_alg_init (struct crypto_tfm *tfm) -{ -return crypto4xx_hash_alg_init (tfm,SA_HASH160_LEN ,SA_HASH_ALG_SHA1 , -SA_HASH_MODE_HASH ); -}
drivers/crypto/amcc/crypto4xx_core.c +1 -42
79 lines not on this page · raw message
drivers/crypto/amcc/crypto4xx_core.h +0 -7
@@ -16,7 +16,6 @@#include <linux/ratelimit.h> #include <linux/mutex.h> #include <linux/scatterlist.h> -#include <crypto/internal/hash.h> #include <crypto/internal/aead.h> #include <crypto/internal/rng.h> #include <crypto/internal/skcipher.h>
@@ -135,7 +134,6 @@ struct crypto4xx_alg_common {u32 type;union {struct skcipher_alg cipher; -struct ahash_alg hash;struct aead_alg aead;struct rng_alg rng; } u;
@@ -182,11 +180,6 @@ int crypto4xx_encrypt_noiv_block(struct skcipher_request *req);int crypto4xx_decrypt_noiv_block (struct skcipher_request *req);int crypto4xx_rfc3686_encrypt (struct skcipher_request *req);int crypto4xx_rfc3686_decrypt (struct skcipher_request *req); -int crypto4xx_sha1_alg_init (struct crypto_tfm *tfm); -int crypto4xx_hash_digest (struct ahash_request *req); -int crypto4xx_hash_final (struct ahash_request *req); -int crypto4xx_hash_update (struct ahash_request *req); -int crypto4xx_hash_init (struct ahash_request *req);/* * Note: Only use this function to copy items that is word aligned.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 337/1266 crypto: crypto4xx - Remove insecure and unused rng_alg
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit 7811ec9e973d2c9e465083699f0c8240b98cb8c4 upstream.
Remove crypto4xx_rng, as it is insecure and unused:
- It has only a 64-bit security strength, which is highly inadequate. This can be seen by the fact that crypto4xx_hw_init() seeds it with only 64 bits of entropy, and the fact that the original commit mentions that it implements ANSI X9.17 Annex C.
Another issue was that this driver didn't implement the crypto_rng API correctly, as crypto4xx_prng_generate() didn't return 0 on success.
- No user of this code is known. It's usable only theoretically via the "rng" algorithm type of AF_ALG. But userspace actually just uses the actual Linux RNG (/dev/random etc) instead. And rng_algs don't contribute entropy to the actual Linux RNG either. (This may have been confused with hwrng, which does contribute entropy.)
--- drivers/crypto/amcc/crypto4xx_core.c | 87 ------------------------- drivers/crypto/amcc/crypto4xx_core.h | 4 -- drivers/crypto/amcc/crypto4xx_reg_def.h | 11 ---- 3 files changed, 102 deletions(-)
drivers/crypto/amcc/crypto4xx_core.c +0 -87
@@ -31,11 +31,9 @@#include <crypto/ctr.h> #include <crypto/gcm.h> #include <crypto/sha1.h> -#include <crypto/rng.h> #include <crypto/scatterwalk.h> #include <crypto/skcipher.h> #include <crypto/internal/aead.h> -#include <crypto/internal/rng.h> #include <crypto/internal/skcipher.h> #include "crypto4xx_reg_def.h" #include "crypto4xx_core.h"
@@ -989,10 +987,6 @@ static int crypto4xx_register_alg(struct crypto4xx_device *sec_dev, rc =crypto_register_aead (&alg->alg.u.aead);break ; -case CRYPTO_ALG_TYPE_RNG : - rc =crypto_register_rng (&alg->alg.u.rng); -break ; -default : rc =crypto_register_skcipher (&alg->alg.u.cipher);break ;
@@ -1018,10 +1012,6 @@ static void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev)crypto_unregister_aead (&alg->alg.u.aead);break ; -case CRYPTO_ALG_TYPE_RNG : -crypto_unregister_rng (&alg->alg.u.rng); -break ; -default :crypto_unregister_skcipher (&alg->alg.u.cipher); }
@@ -1080,69 +1070,6 @@ static irqreturn_t crypto4xx_ce_interrupt_handler_revb(int irq, void *data) PPC4XX_TMO_ERR_INT); } -static int ppc4xx_prng_data_read (struct crypto4xx_device *dev, -u8 *data,unsigned int max) -{ -unsigned int i, curr =0 ; -u32 val[2 ]; - -do { -/* trigger PRN generation */ -writel (PPC4XX_PRNG_CTRL_AUTO_EN , - dev->ce_base +CRYPTO4XX_PRNG_CTRL ); - -for (i =0 ; i <1024 ; i++) { -/* usually 19 iterations are enough */ -if ((readl (dev->ce_base +CRYPTO4XX_PRNG_STAT ) & -CRYPTO4XX_PRNG_STAT_BUSY )) -continue ; - - val[0 ] =readl_be (dev->ce_base +CRYPTO4XX_PRNG_RES_0 ); - val[1 ] =readl_be (dev->ce_base +CRYPTO4XX_PRNG_RES_1 ); -break ; - } -if (i ==1024 ) -return -ETIMEDOUT ; - -if ((max - curr) >=8 ) { -memcpy (data, &val,8 ); - data +=8 ; - curr +=8 ; - }else { -/* copy only remaining bytes */ -memcpy (data, &val, max - curr); -break ; - } - }while (curr < max); - -return curr; -} - -static int crypto4xx_prng_generate (struct crypto_rng *tfm, -const u8 *src,unsigned int slen, -u8 *dstn,unsigned int dlen) -{ -struct rng_alg *alg =crypto_rng_alg (tfm); -struct crypto4xx_alg *amcc_alg; -struct crypto4xx_device *dev; -int ret; - - amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng); - dev = amcc_alg->dev; - -mutex_lock (&dev->core_dev->rng_lock); - ret =ppc4xx_prng_data_read (dev, dstn, dlen); -mutex_unlock (&dev->core_dev->rng_lock); -return ret; -} - - -static int crypto4xx_prng_seed (struct crypto_rng *tfm,const u8 *seed, -unsigned int slen) -{ -return 0 ; -} -/* * Supported Crypto Algorithms */
@@ -1312,18 +1239,6 @@ static struct crypto4xx_alg_common crypto4xx_alg[] = { .cra_module = THIS_MODULE, }, } }, - { .type = CRYPTO_ALG_TYPE_RNG, .u.rng = { - .base = { - .cra_name = "stdrng", - .cra_driver_name = "crypto4xx_rng", - .cra_priority = 300, - .cra_ctxsize = 0, - .cra_module = THIS_MODULE, - }, - .generate = crypto4xx_prng_generate, - .seed = crypto4xx_prng_seed, - .seedsize = 0, - } }, };/*
@@ -1401,7 +1316,6 @@ static int crypto4xx_probe(struct platform_device *ofdev) core_dev->dev->core_dev = core_dev; core_dev->dev->is_revb = is_revb; core_dev->device = dev; -mutex_init (&core_dev->rng_lock);spin_lock_init (&core_dev->lock);INIT_LIST_HEAD (&core_dev->dev->alg_list);ratelimit_default_init (&core_dev->dev->aead_ratelimit);
@@ -1479,7 +1393,6 @@ static int crypto4xx_remove(struct platform_device *ofdev)tasklet_kill (&core_dev->tasklet);/* Un-register with Linux CryptoAPI */ crypto4xx_unregister_alg (core_dev->dev); -mutex_destroy (&core_dev->rng_lock);/* Free all allocated memory */ crypto4xx_stop_all (core_dev);
drivers/crypto/amcc/crypto4xx_core.h +0 -4
@@ -14,10 +14,8 @@#define __CRYPTO4XX_CORE_H__#include <linux/ratelimit.h> -#include <linux/mutex.h> #include <linux/scatterlist.h> #include <crypto/internal/aead.h> -#include <crypto/internal/rng.h> #include <crypto/internal/skcipher.h> #include "crypto4xx_reg_def.h" #include "crypto4xx_sa.h"
@@ -111,7 +109,6 @@ struct crypto4xx_core_device {u32 irq;struct tasklet_struct tasklet;spinlock_t lock; -struct mutex rng_lock; };struct crypto4xx_ctx {
@@ -135,7 +132,6 @@ struct crypto4xx_alg_common {union {struct skcipher_alg cipher;struct aead_alg aead; -struct rng_alg rng; } u; };
drivers/crypto/amcc/crypto4xx_reg_def.h +0 -11
@@ -90,20 +90,9 @@#define CRYPTO4XX_BYTE_ORDER_CFG 0x000600d8#define CRYPTO4XX_ENDIAN_CFG 0x000600d8 -#define CRYPTO4XX_PRNG_STAT 0x00070000 -#define CRYPTO4XX_PRNG_STAT_BUSY 0x1#define CRYPTO4XX_PRNG_CTRL 0x00070004#define CRYPTO4XX_PRNG_SEED_L 0x00070008#define CRYPTO4XX_PRNG_SEED_H 0x0007000c - -#define CRYPTO4XX_PRNG_RES_0 0x00070020 -#define CRYPTO4XX_PRNG_RES_1 0x00070024 -#define CRYPTO4XX_PRNG_RES_2 0x00070028 -#define CRYPTO4XX_PRNG_RES_3 0x0007002C - -#define CRYPTO4XX_PRNG_LFSR_L 0x00070030 -#define CRYPTO4XX_PRNG_LFSR_H 0x00070034 -/* * Initialize CRYPTO ENGINE registers, and memory bases. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 338/1266 crypto: hisi-trng - Remove crypto_rng interface
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit 216a7795ec210bdabd5dad42323eee70bbfc8d90 upstream.
drivers/crypto/hisilicon/trng/trng.c exposes the same hardware through two completely separate interfaces, crypto_rng and hwrng. However, the implementation of this is buggy because it permits generation operations from these interfaces to run concurrently with each other, accessing the same registers. That is, hisi_trng_generate() synchronizes with itself but not with hisi_trng_read(). This results in potential repetition of output from the RNG, output of non-random values, etc.
Fortunately, there's actually no point in hardware RNG drivers implementing the crypto_rng interface. It's not actually used by anything besides the "rng" algorithm type of AF_ALG, which in turn is not actually used in practice. Other crypto_rng hardware drivers are likewise being phased out, leaving just the hwrng support.
Thus, remove it to simplify the code and avoid conflict (and confusion) with the hwrng interface which is the one that actually matters.
--- drivers/crypto/hisilicon/Kconfig | 1 - drivers/crypto/hisilicon/trng/trng.c | 298 +-------------------------- 2 files changed, 2 insertions(+), 297 deletions(-)
drivers/crypto/hisilicon/Kconfig +0 -1
@@ -79,6 +79,5 @@ config CRYPTO_DEV_HISI_TRNG tristate "Support for HISI TRNG Driver" depends on ARM64 && ACPI select HW_RANDOM - select CRYPTO_RNG help Support for HiSilicon TRNG Driver.
drivers/crypto/hisilicon/trng/trng.c +2 -296
355 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 339/1266 bpf: Support for hardening against JIT spraying
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawan Gupta <[email protected]>
commit 96cce16e26dd02a8678f1e87f88a4b5cdb63b995 upstream.
The BPF JIT allocator packs many small programs into larger executable allocations and reuses space within those allocations as programs are loaded and freed. When fresh code is written into space that a previous program occupied, an indirect jump into the new program can reuse a branch prediction left behind by the old one.
Flush the indirect branch predictors before reusing JIT memory so that indirect jumps into a newly written program don't reuse predictions from an old program that occupied the same space.
Introduce bpf_arch_pred_flush_enabled static key and bpf_arch_pred_flush static call for flushing the branch predictors on JIT memory reuse. Architectures that need a flush, can update it to a predictor flush function. By default, its a NOP and does not emit any CALL.
Allocations larger than a pack are not covered by this flush. That is safe because cBPF programs (the unprivileged attack surface) are bounded well below a pack size. Issue a warning if this assumption is ever violated while the flush is active.
--- include/linux/filter.h | 10 ++++++++++ kernel/bpf/core.c | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+)
include/linux/filter.h +10 -0
@@ -22,6 +22,7 @@#include <linux/vmalloc.h> #include <linux/sockptr.h> #include <crypto/sha1.h> +#include <linux/static_call.h> #include <linux/u64_stats_sync.h> #include <net/sch_generic.h>
@@ -1041,6 +1042,15 @@ extern long bpf_jit_limit_max;typedef void (*bpf_jit_fill_hole_t )(void *area,unsigned int size); +/* +* Flush the indirect branch predictors before reusing JIT memory, so that +* indirect jumps into a newly written program don't reuse predictions left +* behind by an old program that occupied the same space. +*/ +void bpf_arch_pred_flush (void ); +DECLARE_STATIC_CALL (bpf_arch_pred_flush, bpf_arch_pred_flush); +DECLARE_STATIC_KEY_FALSE (bpf_pred_flush_enabled); +void bpf_jit_fill_hole_with_zero (void *area,unsigned int size); struct bpf_binary_header *
kernel/bpf/core.c +19 -0
@@ -37,6 +37,7 @@#include <linux/nospec.h> #include <linux/bpf_mem_alloc.h> #include <linux/memcontrol.h> +#include <linux/static_call.h> #include <asm/barrier.h> #include <asm/unaligned.h>
@@ -858,6 +859,15 @@ void bpf_jit_fill_hole_with_zero(void *area, unsigned int size)memset (area,0 , size); } +DEFINE_STATIC_CALL_NULL (bpf_arch_pred_flush, bpf_arch_pred_flush); + +/* +* Enabled once bpf_arch_pred_flush points at a real flush routine. Lets the +* pack allocator test "is a predictor flush wired up at all" with a cheap +* static branch instead of repeatedly querying the static call target. +*/ +DEFINE_STATIC_KEY_FALSE (bpf_pred_flush_enabled); +#define BPF_PROG_SIZE_TO_NBITS (size) (round_up(size, BPF_PROG_CHUNK_SIZE) / BPF_PROG_CHUNK_SIZE)static DEFINE_MUTEX (pack_mutex);
@@ -910,6 +920,14 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)mutex_lock (&pack_mutex);if (size >BPF_PROG_PACK_SIZE ) { +/* +* Allocations larger than a pack get their own pages, and +* predictors are not flushed for such allocation. This is only +* safe because cBPF programs (the unprivileged attack surface) +* are bounded well below a pack size. +*/ +if (static_branch_unlikely (&bpf_pred_flush_enabled)) +pr_warn_once ("BPF: Predictors not flushed for allocations greater than BPF_PROG_PACK_SIZE\n" ); size =round_up (size,PAGE_SIZE ); ptr =bpf_jit_alloc_exec (size);if (ptr) {
@@ -933,6 +951,7 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns) pos =0 ; found_free_area: +static_call_cond (bpf_arch_pred_flush)();bitmap_set (pack->bitmap, pos, nbits); ptr = (void *)(pack->ptr) + (pos <<BPF_PROG_CHUNK_SHIFT );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 340/1266 x86/bugs: Enable IBPB flush on BPF JIT allocation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawan Gupta <[email protected]>
commit a3af84b0fa00ead01fcd0e28b5d773ff25990a0d upstream.
Enable hardening against JIT spraying when Spectre-v2 mitigations are in use. Specifically, issue an IBPB flush on BPF JIT memory reuse. Skip enabling the IBPB flush if the BPF dispatcher is already using a retpoline sequence.
This hardening applies only when BPF-JIT is in use. Guard the enabling under CONFIG_BPF_JIT so that bugs.c still builds with CONFIG_BPF_JIT=n.
[ pawan: Use entry_ibpb() instead of write_ibpb(). JIT hardening enable
moved to spectre_v2_select_mitigation() because there is no spectre_v2_apply_mitigation()]
--- arch/x86/include/asm/nospec-branch.h | 4 +++ arch/x86/kernel/cpu/bugs.c | 50 +++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-)
arch/x86/include/asm/nospec-branch.h +4 -0
@@ -418,6 +418,10 @@ extern void srso_alias_untrain_ret(void);extern void entry_untrain_ret (void );extern void entry_ibpb (void ); +#ifdef CONFIG_BPF_JIT +extern void bpf_arch_ibpb (void ); +#endif +#ifdef CONFIG_X86_64 extern void clear_bhb_loop (void );#endif
arch/x86/kernel/cpu/bugs.c +45 -5
88 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 341/1266 bpf: Restrict JIT predictor flush to cBPF
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawan Gupta <[email protected]>
commit 0bb99f2cfaae6822d734d69722de30af823efdf3 upstream.
Currently predictor flush on memory reuse is done for all BPF JIT allocations, but only cBPF programs can be loaded by an unprivileged user. eBPF is privileged by default, and flushing predictors for all CPUs on every eBPF reuse penalizes the common case for no security benefit.
eBPF allocations can be frequent on busy systems, only flush predictors for cBPF programs. Trampoline and dispatcher allocations also skip the flush as they are eBPF-only.
[pawan: backport dropped "was_classic" hunk for arches that do not
support pack allocator]
--- arch/riscv/net/bpf_jit_core.c | 3 ++- arch/x86/net/bpf_jit_comp.c | 3 ++- include/linux/filter.h | 5 +++-- kernel/bpf/core.c | 13 ++++++++----- kernel/bpf/dispatcher.c | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-)
arch/riscv/net/bpf_jit_core.c +2 -1
@@ -123,7 +123,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)bpf_jit_binary_pack_alloc (prog_size + extable_size, &jit_data->ro_image,sizeof (u32), &jit_data->header, &jit_data->image, - bpf_fill_ill_insns); + bpf_fill_ill_insns, +bpf_prog_was_classic (prog));if (!jit_data->ro_header) { prog = orig_prog; goto out_offset;
arch/x86/net/bpf_jit_comp.c +2 -1
@@ -2927,7 +2927,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)/* allocate module memory for x86 insns and extable */ header =bpf_jit_binary_pack_alloc (roundup (proglen, align) + extable_size, &image, align, &rw_header, &rw_image, - jit_fill_hole); + jit_fill_hole, +bpf_prog_was_classic (prog));if (!header) { prog = orig_prog; goto out_addrs;
include/linux/filter.h +3 -2
@@ -1065,7 +1065,7 @@ void bpf_jit_free(struct bpf_prog *fp);struct bpf_binary_header *bpf_jit_binary_pack_hdr (const struct bpf_prog *fp); -void *bpf_prog_pack_alloc (u32 size,bpf_jit_fill_hole_t bpf_fill_ill_insns); +void *bpf_prog_pack_alloc (u32 size,bpf_jit_fill_hole_t bpf_fill_ill_insns,bool was_classic);void bpf_prog_pack_free (struct bpf_binary_header *hdr);static inline bool bpf_prog_kallsyms_verify_off (const struct bpf_prog *fp)
@@ -1079,7 +1079,8 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **ro_image,unsigned int alignment, struct bpf_binary_header **rw_hdr, u8 **rw_image, - bpf_jit_fill_hole_t bpf_fill_ill_insns); + bpf_jit_fill_hole_t bpf_fill_ill_insns, + bool was_classic);int bpf_jit_binary_pack_finalize (struct bpf_prog *prog,struct bpf_binary_header *ro_header,struct bpf_binary_header *rw_header);
kernel/bpf/core.c +8 -5
@@ -911,7 +911,7 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_insreturn pack; } -void *bpf_prog_pack_alloc (u32 size,bpf_jit_fill_hole_t bpf_fill_ill_insns) +void *bpf_prog_pack_alloc (u32 size,bpf_jit_fill_hole_t bpf_fill_ill_insns,bool was_classic) {unsigned int nbits =BPF_PROG_SIZE_TO_NBITS (size);struct bpf_prog_pack *pack;
@@ -926,7 +926,7 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)* safe because cBPF programs (the unprivileged attack surface) * are bounded well below a pack size. */ -if (static_branch_unlikely (&bpf_pred_flush_enabled)) +if (was_classic &&static_branch_unlikely (&bpf_pred_flush_enabled))pr_warn_once ("BPF: Predictors not flushed for allocations greater than BPF_PROG_PACK_SIZE\n" ); size =round_up (size,PAGE_SIZE ); ptr =bpf_jit_alloc_exec (size);
@@ -951,7 +951,9 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns) pos =0 ; found_free_area: -static_call_cond (bpf_arch_pred_flush)(); +/* Flush only for cBPF as it may contain a crafted gadget */ +if (static_branch_unlikely (&bpf_pred_flush_enabled) && was_classic) +static_call_cond (bpf_arch_pred_flush)();bitmap_set (pack->bitmap, pos, nbits); ptr = (void *)(pack->ptr) + (pos <<BPF_PROG_CHUNK_SHIFT );
@@ -1111,7 +1113,8 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **image_ptr,unsigned int alignment, struct bpf_binary_header **rw_header, u8 **rw_image, - bpf_jit_fill_hole_t bpf_fill_ill_insns) + bpf_jit_fill_hole_t bpf_fill_ill_insns, + bool was_classic) { struct bpf_binary_header *ro_header;u32 size, hole, start;
@@ -1124,7 +1127,7 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **image_ptr,if (bpf_jit_charge_modmem (size))return NULL ; - ro_header =bpf_prog_pack_alloc (size, bpf_fill_ill_insns); + ro_header =bpf_prog_pack_alloc (size, bpf_fill_ill_insns, was_classic);if (!ro_header) {bpf_jit_uncharge_modmem (size);return NULL ;
kernel/bpf/dispatcher.c +1 -1
@@ -145,7 +145,7 @@ void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from,mutex_lock (&d->mutex);if (!d->image) { - d->image =bpf_prog_pack_alloc (PAGE_SIZE , bpf_jit_fill_hole_with_zero); + d->image =bpf_prog_pack_alloc (PAGE_SIZE , bpf_jit_fill_hole_with_zero, false);if (!d->image) goto out; d->rw_image =bpf_jit_alloc_exec (PAGE_SIZE );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 342/1266 bpf: Skip redundant IBPB in pack allocator
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawan Gupta <[email protected]>
commit a23c1c5396a91680703360d1ee28a44657c503c4 upstream.
bpf_prog_pack_alloc() issues IBPB on all CPUs on every cBPF allocation, even when reusing chunks from an existing pack where no new memory was touched since the last IBPB.
Since IBPB on all CPUs is heavy, Dave Hansen suggested to track allocation since last IBPB, and only issue IBPB at reuse for the chunks that have not seen an IBPB since they were last freed.
Track per-pack whether an IBPB is needed via arch_flush_needed. Set it when allocating a chunk, reset on IBPB flush. On reuse, conditionally issue the flush. Since IBPB invalidates all BTB entries, clear the flag on all packs after flushing.
--- kernel/bpf/core.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
kernel/bpf/core.c +14 -1
@@ -851,6 +851,7 @@ int bpf_jit_add_poke_descriptor(struct bpf_prog *prog,struct bpf_prog_pack {struct list_head list;void *ptr; +bool arch_flush_needed;unsigned long bitmap[]; };
@@ -906,6 +907,8 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_insbitmap_zero (pack->bitmap,BPF_PROG_PACK_SIZE /BPF_PROG_CHUNK_SIZE );list_add_tail (&pack->list, &pack_list); +if (static_branch_unlikely (&bpf_pred_flush_enabled)) + pack->arch_flush_needed = true;set_vm_flush_reset_perms (pack->ptr);set_memory_rox ((unsigned long )pack->ptr,BPF_PROG_PACK_SIZE /PAGE_SIZE );return pack;
@@ -952,8 +955,15 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool found_free_area:/* Flush only for cBPF as it may contain a crafted gadget */ -if (static_branch_unlikely (&bpf_pred_flush_enabled) && was_classic) +if (static_branch_unlikely (&bpf_pred_flush_enabled) && + pack->arch_flush_needed && + was_classic) { +struct bpf_prog_pack *p; +static_call_cond (bpf_arch_pred_flush)(); +list_for_each_entry (p, &pack_list, list) + p->arch_flush_needed = false; + }bitmap_set (pack->bitmap, pos, nbits); ptr = (void *)(pack->ptr) + (pos <<BPF_PROG_CHUNK_SHIFT );
@@ -991,6 +1001,9 @@ void bpf_prog_pack_free(struct bpf_binary_header *hdr) "bpf_prog_pack bug: missing bpf_arch_text_invalidate?\n");bitmap_clear (pack->bitmap, pos, nbits); + +if (static_branch_unlikely (&bpf_pred_flush_enabled)) + pack->arch_flush_needed = true;if (bitmap_find_next_zero_area (pack->bitmap,BPF_PROG_CHUNK_COUNT ,0 ,BPF_PROG_CHUNK_COUNT ,0 ) ==0 ) {list_del (&pack->list);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 343/1266 bpf: Prefer packs that wont trigger an IBPB flush on allocation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawan Gupta <[email protected]>
commit a9b1f19a6a673ba06820898d0f1ad02883ea1639 upstream.
Currently BPF pack allocator picks the chunks from the first available pack. While this is okay, it naturally leads to more frequent flushes when there are multiple packs in the system that weren't used since the last flush.
As an optimization prefer allocating the new programs from packs that are unused since last flush. When all packs are dirty, allocation forces a flush and marks all packs clean.
Below are some future optimizations ideas:
1. Currently, the "dirty" tracking is only done at the pack-level. Flush frequency can further be reduced with chunk-level tracking. This requires a new bitmap per-pack to track the dirty state.
2. IBPB flush is done on all CPUs, even if only a single CPU ran the BPF program. On a system with hundreds of CPUs this could be a major bottleneck forcing hundreds of IPIs to deliver the flush. The solution is to track the CPUs where a BPF program ran, and issue IBPB only on those CPUs.
3. Avoid IBPB when flush is already done at other sources (e.g. context switch).
--- kernel/bpf/core.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-)
kernel/bpf/core.c +24 -3
@@ -917,8 +917,8 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_insvoid *bpf_prog_pack_alloc (u32 size,bpf_jit_fill_hole_t bpf_fill_ill_insns,bool was_classic) {unsigned int nbits =BPF_PROG_SIZE_TO_NBITS (size); -struct bpf_prog_pack *pack; -unsigned long pos; +struct bpf_prog_pack *pack, *fallback_pack =NULL ; +unsigned long pos, fallback_pos =0 ;void *ptr =NULL ;mutex_lock (&pack_mutex);
@@ -943,8 +943,29 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, boollist_for_each_entry (pack, &pack_list, list) { pos =bitmap_find_next_zero_area (pack->bitmap,BPF_PROG_CHUNK_COUNT ,0 , nbits,0 ); -if (pos <BPF_PROG_CHUNK_COUNT ) +if (pos >=BPF_PROG_CHUNK_COUNT ) +continue ; +/* Flush not enabled, use any pack */ +if (!static_branch_unlikely (&bpf_pred_flush_enabled)) goto found_free_area; +/* +* cBPF reuse of a dirty pack triggers a flush, so prefer a +* clean pack for cBPF. eBPF never flushes, so pick the first +* free pack, dirty or clean. +*/ +if (!was_classic || !pack->arch_flush_needed) + goto found_free_area; +if (!fallback_pack) { + fallback_pack = pack; + fallback_pos = pos; + } + } + +/* No preferred pack found */ +if (fallback_pack) { + pack = fallback_pack; + pos = fallback_pos; + goto found_free_area; } pack =alloc_new_pack (bpf_fill_ill_insns);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 344/1266 bpf: Prefer dirty packs for eBPF allocations
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawan Gupta <[email protected]>
commit b72e29e0f7ee329d89f86db8700c8ea99b4a370a upstream.
The pack allocator only flushes predictors when reusing a dirty pack for cBPF, eBPF allocations never trigger a flush. Currently, eBPF picks the first free pack, which could be a clean pack. As an optimization, leaving a clean pack for cBPF can avoid flushes.
Prefer dirty packs for eBPF and keep clean packs free for cBPF. This mirrors the existing cBPF preference for clean packs: each program kind prefers the pack that avoids an extra flush, and falls back to the other kind only when no preferred pack has room. eBPF reuse of a dirty pack is harmless since eBPF being privileged does not flush.
--- kernel/bpf/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
kernel/bpf/core.c +3 -3
@@ -950,10 +950,10 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool goto found_free_area;/* * cBPF reuse of a dirty pack triggers a flush, so prefer a -* clean pack for cBPF. eBPF never flushes, so pick the first -* free pack, dirty or clean. +* clean pack for cBPF. eBPF never flushes, so steer it to a +* dirty pack and keep clean packs free for cBPF. */ -if (!was_classic || !pack->arch_flush_needed) +if (was_classic ^ pack->arch_flush_needed) goto found_free_area;if (!fallback_pack) { fallback_pack = pack;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 345/1266 media: uvcvideo: Avoid partial metadata buffers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Ribalda <[email protected]>
commit a15b773fe4ffa450b56347cc506b2d1405600f5d upstream.
If the metadata queue that is empty receives a new buffer while we are in the middle of processing a frame, the first metadata buffer will contain partial information.
Avoid this by tracking the state of the metadata buffer and making sure that it is in sync with the data buffer.
Now that we are at it, make sure that we skip buffers of size 1 or 0. They are not allowed by the spec... but it is a simple check to add and better be safe than sorry.
--- drivers/media/usb/uvc/uvc_video.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/media/usb/uvc/uvc_video.c +9 -4
@@ -1122,7 +1122,9 @@ static void uvc_video_stats_stop(struct* uvc_video_decode_end will never be called with a NULL buffer. */ static int uvc_video_decode_start (struct uvc_streaming *stream, -struct uvc_buffer *buf,const u8 *data,int len) +struct uvc_buffer *buf, +struct uvc_buffer *meta_buf, +const u8 *data,int len) {u8 header_len;u8 fid;
@@ -1195,6 +1197,8 @@ static int uvc_video_decode_start(struct/* TODO: Handle PTS and SCR. */ buf->state =UVC_BUF_STATE_ACTIVE ; +if (meta_buf) + meta_buf->state =UVC_BUF_STATE_ACTIVE ; }/*
@@ -1411,7 +1415,7 @@ static void uvc_video_decode_meta(structktime_t time;const u8 *scr; -if (!meta_buf || length ==2 ) +if (length <=2 || !meta_buf || meta_buf->state !=UVC_BUF_STATE_ACTIVE )return ; has_pts = mem[1 ] &UVC_STREAM_PTS ;
@@ -1528,7 +1532,7 @@ static void uvc_video_decode_isoc(struct/* Decode the payload header. */ mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset; do { - ret = uvc_video_decode_start(stream, buf, mem, + ret = uvc_video_decode_start(stream, buf, meta_buf, mem, urb->iso_frame_desc[i].actual_length); if (ret == -EAGAIN) uvc_video_next_buffers(stream, &buf, &meta_buf);
@@ -1577,7 +1581,8 @@ static void uvc_video_decode_bulk(struct*/ if (stream->bulk.header_size ==0 && !stream->bulk.skip_payload) {do { - ret =uvc_video_decode_start (stream, buf, mem, len); + ret =uvc_video_decode_start (stream, buf, meta_buf, mem, + len);if (ret == -EAGAIN )uvc_video_next_buffers (stream, &buf, &meta_buf); }while (ret == -EAGAIN );
Greg Kroah-Hartman
maintainerPATCH 346/1266 media: uvcvideo: Fix buffer sequence in frame gaps
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Ribalda <[email protected]>
commit 2f24ac8dd87983a55f0498898f34a5f2b735b802 upstream.
In UVC, the FID flips with every frame. For every FID flip, we increase the stream sequence number.
Now, if a FID flips multiple times and there is no data transferred between the flips, the buffer sequence number will be set to the value of the stream sequence number after the first flip.
Userspace uses the buffer sequence number to determine if there have been missing frames. With the current behaviour, userspace will think that the gap is in the wrong location.
This patch modifies uvc_video_decode_start() to provide the correct buffer sequence number and timestamp.
--- drivers/media/usb/uvc/uvc_video.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/media/usb/uvc/uvc_video.c +13 -4
@@ -1151,6 +1151,19 @@ static int uvc_video_decode_start(struct stream->sequence++;if (stream->sequence)uvc_video_stats_update (stream); + +/* +* On a FID flip initialize sequence number and timestamp. +* +* The driver already takes care of injecting FID flips for +* UVC_QUIRK_STREAM_NO_FID and UVC_QUIRK_MJPEG_NO_EOF. +*/ +if (buf) { + buf->buf.field =V4L2_FIELD_NONE ; + buf->buf.sequence = stream->sequence; + buf->buf.vb2_buf.timestamp = +ktime_to_ns (uvc_video_get_time ()); + } }uvc_video_clock_decode (stream, buf, data, len);
@@ -1191,10 +1204,6 @@ static int uvc_video_decode_start(structreturn -ENODATA ; } - buf->buf.field =V4L2_FIELD_NONE ; - buf->buf.sequence = stream->sequence; - buf->buf.vb2_buf.timestamp =ktime_to_ns (uvc_video_get_time ()); -/* TODO: Handle PTS and SCR. */ buf->state =UVC_BUF_STATE_ACTIVE ;if (meta_buf)
Greg Kroah-Hartman
maintainerPATCH 347/1266 media: uvcvideo: Fix sequence number when no EOF
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Ribalda <[email protected]>
commit f078966ca1fb1b3865d8e6bbe2705cfd277fc637 upstream.
If the driver could not detect the EOF, the sequence number is increased twice:
1) When we enter uvc_video_decode_start() with the old buffer and FID has flipped => We return -EAGAIN and last_fid is not flipped
2) When we enter uvc_video_decode_start() with the new buffer.
Fix this issue by moving the new frame detection logic earlier in uvc_video_decode_start().
This also has some nice side affects:
- The error status from the new packet will no longer get propagated to the previous frame-buffer.
- uvc_video_clock_decode() will no longer update the previous frame buf->stf with info from the new packet.
- uvc_video_clock_decode() and uvc_video_stats_decode() will no longer get called twice for the same packet.
--- drivers/media/usb/uvc/uvc_video.c | 92 +++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 45 deletions(-)
drivers/media/usb/uvc/uvc_video.c +47 -45
@@ -1144,6 +1144,53 @@ static int uvc_video_decode_start(struct fid = data[1 ] &UVC_STREAM_FID ;/* +* Mark the buffer as done if we're at the beginning of a new frame. +* End of frame detection is better implemented by checking the EOF +* bit (FID bit toggling is delayed by one frame compared to the EOF +* bit), but some devices don't set the bit at end of frame (and the +* last payload can be lost anyway). We thus must check if the FID has +* been toggled. +* +* stream->last_fid is initialized to -1, and buf->bytesused to 0, +* so the first isochronous frame will never trigger an end of frame +* detection. +* +* Empty buffers (bytesused == 0) don't trigger end of frame detection +* as it doesn't make sense to return an empty buffer. This also +* avoids detecting end of frame conditions at FID toggling if the +* previous payload had the EOF bit set. +*/ +if (fid != stream->last_fid && buf && buf->bytesused !=0 ) { +uvc_dbg (stream->dev,FRAME , +"Frame complete (FID bit toggled)\n" ); + buf->state =UVC_BUF_STATE_READY ; + +return -EAGAIN ; + } + +/* +* Some cameras, when running two parallel streams (one MJPEG alongside +* another non-MJPEG stream), are known to lose the EOF packet for a frame. +* We can detect the end of a frame by checking for a new SOI marker, as +* the SOI always lies on the packet boundary between two frames for +* these devices. +*/ +if (stream->dev->quirks &UVC_QUIRK_MJPEG_NO_EOF && + (stream->cur_format->fcc ==V4L2_PIX_FMT_MJPEG || + stream->cur_format->fcc ==V4L2_PIX_FMT_JPEG ) && + buf && buf->bytesused !=0 ) { +const u8 *packet = data + header_len; + +if (len >= header_len +2 && + packet[0 ] ==0xff && packet[1 ] ==JPEG_MARKER_SOI ) { + buf->state =UVC_BUF_STATE_READY ; + buf->error =1 ; + stream->last_fid ^=UVC_STREAM_FID ; +return -EAGAIN ; + } + } + +/* * Increase the sequence number regardless of any buffer states, so * that discontinuous sequence numbers always indicate lost frames. */
@@ -1210,51 +1257,6 @@ static int uvc_video_decode_start(struct meta_buf->state =UVC_BUF_STATE_ACTIVE ; } -/* -* Mark the buffer as done if we're at the beginning of a new frame. -* End of frame detection is better implemented by checking the EOF -* bit (FID bit toggling is delayed by one frame compared to the EOF -* bit), but some devices don't set the bit at end of frame (and the -* last payload can be lost anyway). We thus must check if the FID has -* been toggled. -* -* stream->last_fid is initialized to -1, so the first isochronous -* frame will never trigger an end of frame detection. -* -* Empty buffers (bytesused == 0) don't trigger end of frame detection -* as it doesn't make sense to return an empty buffer. This also -* avoids detecting end of frame conditions at FID toggling if the -* previous payload had the EOF bit set. -*/ -if (fid != stream->last_fid && buf->bytesused !=0 ) { -uvc_dbg (stream->dev,FRAME , -"Frame complete (FID bit toggled)\n" ); - buf->state =UVC_BUF_STATE_READY ; -return -EAGAIN ; - } - -/* -* Some cameras, when running two parallel streams (one MJPEG alongside -* another non-MJPEG stream), are known to lose the EOF packet for a frame. -* We can detect the end of a frame by checking for a new SOI marker, as -* the SOI always lies on the packet boundary between two frames for -* these devices. -*/ -if (stream->dev->quirks &UVC_QUIRK_MJPEG_NO_EOF && - (stream->cur_format->fcc ==V4L2_PIX_FMT_MJPEG || - stream->cur_format->fcc ==V4L2_PIX_FMT_JPEG )) { -const u8 *packet = data + header_len; - -if (len >= header_len +2 && - packet[0 ] ==0xff && packet[1 ] ==JPEG_MARKER_SOI && - buf->bytesused !=0 ) { - buf->state =UVC_BUF_STATE_READY ; - buf->error =1 ; - stream->last_fid ^=UVC_STREAM_FID ; -return -EAGAIN ; - } - } - stream->last_fid = fid;return header_len;
Greg Kroah-Hartman
maintainerPATCH 348/1266 dt-bindings: media: sun4i-a10-video-engine: Add interconnect properties
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
commit 018f2dc3a42098d3b04edd1480adc51d268adb14 upstream.
The Allwinner video engine sits behind the MBUS that is represented as an interconnect.
Make sure that the interconnect properties are valid in the binding.
--- Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml +10 -0
@@ -63,6 +63,16 @@ properties: CMA pool to use for buffers allocation instead of the default CMA pool. + # FIXME: This should be made required eventually once every SoC will + # have the MBUS declared. + interconnects: + maxItems: 1 + + # FIXME: This should be made required eventually once every SoC will + # have the MBUS declared. + interconnect-names: + const: dma-mem + required: - compatible - reg
Greg Kroah-Hartman
maintainerPATCH 349/1266 dt-bindings: power: imx93: Add MIPI PHY power domain
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guoniu Zhou <[email protected]>
commit 6aa38ef0eab32df5409b72d62509de6ba09cea50 upstream.
Add MIPI PHY power domain for shared PHY resources used by both MIPI DSI and CSI blocks.
--- include/dt-bindings/power/fsl,imx93-power.h | 1 + 1 file changed, 1 insertion(+)
include/dt-bindings/power/fsl,imx93-power.h +1 -0
@@ -11,5 +11,6 @@#define IMX93_MEDIABLK_PD_PXP 2#define IMX93_MEDIABLK_PD_LCDIF 3#define IMX93_MEDIABLK_PD_ISI 4 +#define IMX93_MEDIABLK_PD_MIPI_PHY 5#endif
Greg Kroah-Hartman
maintainerPATCH 350/1266 serial: msm: Disable DMA for kernel console UART
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephan Gerhold <[email protected]>
commit 22dd2777e6c180e1c945b00f6d18550979436324 upstream.
At the moment, concurrent writes from userspace and the kernel to the console can trigger a race condition that results in an infinite loop of the same messages printed over and over again. This is most likely to happen during system startup or shutdown when the init system starts/stops a large number of system services that interact with various kernel code.
When userspace writes to the TTY device, the driver initiates an asynchronous DMA transfer and releases the port lock. At the same moment, the kernel printk path might grab the port lock and re-configure the UART controller for PIO, without waiting for the DMA operation to complete. It seems like this collision results in zero progress being reported for the DMA engine, so the same text is printed to the console over and over again.
For the kernel console, we want a reliable output path that will be functional even during crashes etc. So rather than implementing complex code to synchronize the kernel console write routines with the userspace DMA write routines, simply disable DMA for the console UART instance.
Similar checks exist in many other serial drivers, e.g. 8250_port.c, imx.c, sh-sci.c etc.
--- drivers/tty/serial/msm_serial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/tty/serial/msm_serial.c +2 -1
@@ -1221,7 +1221,8 @@ static int msm_startup(struct uart_port data |=MSM_UART_MR1_AUTO_RFR_LEVEL0 & rfr_level;msm_write (port, data,MSM_UART_MR1 ); -if (msm_port->is_uartdm) { +/* Disable DMA for console to prevent PIO/DMA collisions */ +if (msm_port->is_uartdm && !uart_console (port)) {msm_request_tx_dma (msm_port, msm_port->uart.mapbase);msm_request_rx_dma (msm_port, msm_port->uart.mapbase); }
Greg Kroah-Hartman
maintainerPATCH 351/1266 serial: 8250_omap: clear rx_running on zero-length DMA completes
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthias Feser <[email protected]>
commit 061b627ba534230a18ec4d7251562af12325d06a upstream.
On AM33xx RX DMA only triggers when the FIFO reaches the configured threshold (typically 48 bytes). For smaller bursts no DMA request is issued and the FIFO is drained by RX timeout.
In this case __dma_rx_do_complete() can legitimately see count == 0.
The current code exits early in this case and does not clear dma->rx_running, leaving the DMA state inconsistent. This can prevent RX DMA from restarting and may cause omap_8250_rx_dma_flush() to fail, marking DMA as broken.
Fix this by clearing dma->rx_running once the DMA transfer has completed or been terminated, even if no data was transferred.
--- drivers/tty/serial/8250/8250_omap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/tty/serial/8250/8250_omap.c +2 -1
@@ -953,11 +953,12 @@ static void __dma_rx_do_complete(structdev_err (p->port.dev,"teardown incomplete\n" ); } } + + dma->rx_running =0 ;if (!count) goto out; ret =tty_insert_flip_string (tty_port, dma->rx_buf, count); - dma->rx_running =0 ; p->port.icount.rx += ret; p->port.icount.buf_overrun += count - ret; out:
Greg Kroah-Hartman
maintainerPATCH 352/1266 rxrpc: rxrpc_verify_data ensure rx_dec_buffer alloc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeffrey Altman <[email protected]>
commit 16c8ae9735c5bd7e54dd7478d6348e0fc860842d upstream.
rxrpc_recvmsg_data() calls rxrpc_verify_data() whenever the rxrpc_call.rx_dec_buffer is unallocated and assumes that upon successful return that rx_dec_buffer must be allocated. However, rxrpc_verify_data() does not request an allocation if the rxrpc_skb_priv.len is zero.
In addition, failure to allocate rx_dec_buffer will result in a call to skb_copy_bits() with a NULL destination which can trigger a NULL pointer dereference.
To prevent these issues rxrpc_verify_data() is modified to always attempt to allocate the rxrpc_call.rx_dec_buffer if it is NULL.
This issue was identified with assistance of a private sashiko instance.
--- net/rxrpc/recvmsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/rxrpc/recvmsg.c +1 -1
@@ -157,7 +157,7 @@ static int rxrpc_verify_data(struct rxrpstruct rxrpc_skb_priv *sp =rxrpc_skb (skb);int ret; -if (sp->len > call->rx_dec_bsize) { +if (sp->len > call->rx_dec_bsize || !call->rx_dec_buffer) {/* Make sure we can hold a 1412-byte jumbo subpacket and make * sure that the buffer size is aligned to a crypto blocksize. */
Greg Kroah-Hartman
maintainerPATCH 353/1266 rxrpc: Fix leak of released call in recvmsg(MSG_PEEK)
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
commit 4bdb9e471f5b1ac9cbe4add5de7ff085a0ec303c upstream.
Fix rxrpc_recvmsg() to also drop the ref it holds on an already-released call if MSG_PEEK is in force (the function holds a ref on the call irrespective of whether MSG_PEEK is specified or not).
--- net/rxrpc/recvmsg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/rxrpc/recvmsg.c +1 -2
@@ -429,8 +429,7 @@ try_again:if (test_bit (RXRPC_CALL_RELEASED , &call->flags)) {rxrpc_see_call (call, rxrpc_call_see_already_released);mutex_unlock (&call->user_mutex); -if (!(flags &MSG_PEEK )) -rxrpc_put_call (call, rxrpc_call_put_recvmsg); +rxrpc_put_call (call, rxrpc_call_put_recvmsg); goto try_again; }
Greg Kroah-Hartman
maintainerPATCH 354/1266 afs: Fix netns teardown to cancel the preallocation charger
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
commit 47694fbc9d24ab6bf210f91e8efe06a10a478064 upstream.
Fix the teardown of an afs network namespace to make sure it cancels the work item that keeps the preallocated rxrpc call/conn/peer queue charged before incoming calls are disabled (i.e. listen 0).
Also, if net->live is false because the afs netns is being deleted, make afs_charge_preallocation() skip charging and make afs_rx_new_call() avoid requeuing the charger.
(This was found by AI review).
--- fs/afs/rxrpc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/afs/rxrpc.c +4 -2
@@ -109,6 +109,7 @@ void afs_close_socket(struct afs_net *ne {_enter ("" ); +cancel_work_sync (&net->charge_preallocation_work);kernel_listen (net->socket,0 );flush_workqueue (afs_async_calls);
@@ -727,7 +728,7 @@ void afs_charge_preallocation(struct wor container_of(work, struct afs_net, charge_preallocation_work);struct afs_call *call = net->spare_incoming_call; -for (;;) { +while (READ_ONCE (net->live)) {if (!call) { call =afs_alloc_call (net, &afs_RXCMxxxx,GFP_KERNEL );if (!call)
@@ -772,7 +773,8 @@ static void afs_rx_new_call(struct sock {struct afs_net *net =afs_sock2net (sk); -queue_work (afs_wq, &net->charge_preallocation_work); +if (net->live) +queue_work (afs_wq, &net->charge_preallocation_work); }/*
Greg Kroah-Hartman
maintainerPATCH 355/1266 afs: fix NULL pointer dereference in afs_get_tree()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matvey Kovalev <[email protected]>
commit 0b70716081c6462be9b2928ad736d0d527b09678 upstream.
afs_alloc_sbi() uses kzalloc for memory allocation. And, if ctx->dyn_root is not null, as->cell and as->volume are null. In trace_afs_get_tree() they are dereferenced.
KASAN error message:
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 2 PID: 18478 Comm: syz-executor.7 Not tainted 5.10.246-syzkaller #0 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014 RIP: 0010:perf_trace_afs_get_tree+0x1d9/0x550
include/trace/events/afs.h:1365
Call Trace: trace_afs_get_tree include/trace/events/afs.h:1365 [inline] afs_get_tree+0x922/0x1350 fs/afs/super.c:599 vfs_get_tree+0x8e/0x300 fs/super.c:1572 do_new_mount fs/namespace.c:3011 [inline] path_mount+0x14a5/0x2220 fs/namespace.c:3341 do_mount fs/namespace.c:3354 [inline] __do_sys_mount fs/namespace.c:3562 [inline] __se_sys_mount fs/namespace.c:3539 [inline] __x64_sys_mount+0x283/0x300 fs/namespace.c:3539 do_syscall_64+0x33/0x50 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x67/0xd1
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
--- fs/afs/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/afs/super.c +2 -1
@@ -597,7 +597,8 @@ static int afs_get_tree(struct fs_contex } fc->root =dget (sb->s_root); -trace_afs_get_tree (as->cell, as->volume); +if (!ctx->dyn_root) +trace_afs_get_tree (as->cell, as->volume);_leave (" = 0 [%p]" , sb);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 356/1266 afs: Fix further netns teardown to cancel the preallocation charger
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
commit 2daf8ac812c3d78c642fe7652f62e29df5e3da20 upstream.
When an afs network namespace is torn down, it cancels and waits for the work item that keeps the preallocated rxrpc call/conn/peer queue charged before disabling incoming (i.e. listen 0), but there's a small window in which it can be requeued by an incoming call wending through the I/O thread.
Fix this by cancelling the charger work item again after reducing the listen backlog to zero.
--- fs/afs/rxrpc.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/afs/rxrpc.c +5 -0
@@ -110,8 +110,13 @@ void afs_close_socket(struct afs_net *ne_enter ("" );cancel_work_sync (&net->charge_preallocation_work); +/* Future work items should now see ->live is false. */ +kernel_listen (net->socket,0 ); + +/* Make sure work items are no longer running. */ flush_workqueue (afs_async_calls); +cancel_work_sync (&net->charge_preallocation_work);if (net->spare_incoming_call) {afs_put_call (net->spare_incoming_call);
Greg Kroah-Hartman
maintainerPATCH 357/1266 fbcon: fix NULL pointer dereference for a console without vc_data
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Bridges <[email protected]>
commit 5fae9a928482d4845bca169a3a098789203a1ca4 upstream.
fbcon_new_modelist() runs when a framebuffer's modelist changes. For each console mapped to it with fb_display[i].mode set, it reads vc_cons[i].d and passes the vc_num to fbcon_set_disp(). This assumes a console with a mode set has a vc_data, but it can be NULL. fbcon_set_disp() sets fb_display[i].mode before it checks vc_data, and fbcon_deinit() leaves the mode set after the vc_data is freed. fbcon_new_modelist() then dereferences the NULL vc_data.
Keep fb_display[i].mode set only while the console has a vc_data. Check vc_data before setting the mode in fbcon_set_disp(), and clear the mode in fbcon_deinit(). The existing mode check in fbcon_new_modelist() then skips such consoles.
--- drivers/video/fbdev/core/fbcon.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/video/fbdev/core/fbcon.c +4 -3
@@ -1183,6 +1183,7 @@ static void fbcon_deinit(struct vc_dataint idx;fbcon_free_font (p); + p->mode =NULL ; idx = con2fb_map[vc->vc_num];if (idx ==-1 )
@@ -1361,14 +1362,14 @@ static void fbcon_set_disp(struct fb_inf p = &fb_display[unit]; -if (var_to_display (p, var, info)) -return ; - vc = vc_cons[unit].d;if (!vc)return ; +if (var_to_display (p, var, info)) +return ; + default_mode = vc->vc_display_fg; svc = *default_mode; t = &fb_display[svc->vc_num];
Greg Kroah-Hartman
maintainerPATCH 358/1266 clocksource/drivers/sun5i: Handle error returns from devm_reset_control_get_optional_exclusive()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Ni <[email protected]>
[ Upstream commit fed9f727cc3f91dde8278961269419083502b40e ]
The devm_reset_control_get_optional_exclusive() function may return an ERR_PTR in case of genuine reset control acquisition errors, not just NULL which indicates the legitimate absence of an optional reset.
Add an IS_ERR() check after the call in sun5i_timer_probe(). On error, return the error code to ensure proper failure handling rather than proceeding with invalid pointers.
--- drivers/clocksource/timer-sun5i.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/clocksource/timer-sun5i.c +3 -0
@@ -286,6 +286,9 @@ static int sun5i_timer_probe(struct platform_device *pdev) } rstc =devm_reset_control_get_optional_exclusive (dev,NULL ); +if (IS_ERR (rstc)) +return dev_err_probe (dev,PTR_ERR (rstc), +"failed to get reset\n" );if (rstc)reset_control_deassert (rstc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 359/1266 drm/rockchip: Test for imported buffers with drm_gem_is_imported()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
[ Upstream commit 9fc0da81916250f343599a4dd259f097196bf0fb ]
Instead of testing import_attach for imported GEM buffers, invoke drm_gem_is_imported() to do the test. The test itself does not change.
--- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/rockchip/rockchip_drm_gem.c +1 -1
@@ -332,7 +332,7 @@ void rockchip_gem_free_object(struct drm_gem_object *obj)struct rockchip_drm_private *private = drm->dev_private;struct rockchip_gem_object *rk_obj =to_rockchip_obj (obj); -if (obj->import_attach) { +if (drm_gem_is_imported (obj)) {if (private->domain) {rockchip_gem_iommu_unmap (rk_obj); }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 360/1266 drm/tidss: Drop extra drm_mode_config_reset() call
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomi Valkeinen <[email protected]>
[ Upstream commit f468fef38716f667e805e0fa2c497c6b9c325bb9 ]
We are calling drm_mode_config_reset() twice at probe time. There's no reason for this and the second call can be removed, reducing work at probe time slightly.
--- drivers/gpu/drm/tidss/tidss_kms.c | 2 -- 1 file changed, 2 deletions(-)
drivers/gpu/drm/tidss/tidss_kms.c +0 -2
@@ -268,8 +268,6 @@ int tidss_modeset_init(struct tidss_device *tidss)if (ret)return ret; -drm_mode_config_reset (ddev); -dev_dbg (tidss->dev,"%s done\n" , __func__);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 361/1266 drm/amdgpu: fix integer overflow in amdgpu_gem_align_pitch()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Werner Kasselman <[email protected]>
[ Upstream commit fc3659f178d4a65599167d5a648bbeef4b0d4446 ]
amdgpu_gem_align_pitch() is passed u32 width and cpp from dumb buffer creation but uses signed int internally. The round-up add and the aligned * cpp multiplication can overflow, returning zero or a negative pitch. A zero pitch propagates to a zero-sized GEM object allocation that reaches userspace via DRM_IOCTL_MODE_CREATE_DUMB.
Switch the helper to unsigned int and use check_add_overflow() / check_mul_overflow() so wraparound returns zero. Reject a zero pitch or size in amdgpu_mode_dumb_create() rather than allocating a zero- byte BO.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +17 -8
@@ -27,6 +27,7 @@*/ #include <linux/ktime.h> #include <linux/module.h> +#include <linux/overflow.h> #include <linux/pagemap.h> #include <linux/pci.h> #include <linux/dma-buf.h>
@@ -878,13 +879,14 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,return r; } -static int amdgpu_gem_align_pitch (struct amdgpu_device *adev, -int width, -int cpp, -bool tiled) +static unsigned int amdgpu_gem_align_pitch (struct amdgpu_device *adev, +unsigned int width, +unsigned int cpp, +bool tiled) { -int aligned = width; -int pitch_mask =0 ; +unsigned int aligned = width; +unsigned int pitch_mask =0 ; +unsigned int pitch;switch (cpp) {case 1 :
@@ -899,9 +901,12 @@ static int amdgpu_gem_align_pitch(struct amdgpu_device *adev,break ; } - aligned += pitch_mask; +if (check_add_overflow (aligned, pitch_mask, &aligned)) +return 0 ; aligned &= ~pitch_mask; -return aligned * cpp; +if (check_mul_overflow (aligned, cpp, &pitch)) +return 0 ; +return pitch; } int amdgpu_mode_dumb_create(struct drm_file *file_priv,
@@ -928,8 +933,12 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, args->pitch =amdgpu_gem_align_pitch (adev, args->width,DIV_ROUND_UP (args->bpp,8 ),0 ); +if (!args->pitch) +return -EINVAL ; args->size = (u64 )args->pitch * args->height; args->size =ALIGN (args->size,PAGE_SIZE ); +if (!args->size) +return -EINVAL ; domain =amdgpu_bo_get_preferred_domain (adev,amdgpu_display_supported_domains (adev, flags)); r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 362/1266 drm/radeon: fix integer overflow in radeon_align_pitch()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Werner Kasselman <[email protected]>
[ Upstream commit ce3b24eb3ee8f82de851535f516bf21f83e82259 ]
radeon_align_pitch() has the same kind of overflow issue as the old amdgpu helper: both the alignment round-up add and the final 'aligned * cpp' calculation can overflow signed int.
If that wraps, radeon_mode_dumb_create() can end up returning an invalid pitch or creating a zero-sized dumb buffer.
Fix this by using check_add_overflow() for the alignment round-up and check_mul_overflow() for the final pitch calculation, returning 0 on overflow. Also reject zero pitch and size in radeon_mode_dumb_create().
Found via AST-based call-graph analysis using sqry.
--- drivers/gpu/drm/radeon/radeon_gem.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/radeon_gem.c +11 -2
@@ -27,6 +27,7 @@*/ #include <linux/iosys-map.h> +#include <linux/overflow.h> #include <linux/pci.h> #include <drm/drm_device.h>
@@ -809,6 +810,7 @@ int radeon_align_pitch(struct radeon_device *rdev, int width, int cpp, bool tileint aligned = width;int align_large = (ASIC_IS_AVIVO (rdev)) || tiled;int pitch_mask =0 ; +int pitch;switch (cpp) {case 1 :
@@ -823,9 +825,12 @@ int radeon_align_pitch(struct radeon_device *rdev, int width, int cpp, bool tilebreak ; } - aligned += pitch_mask; +if (check_add_overflow (aligned, pitch_mask, &aligned)) +return 0 ; aligned &= ~pitch_mask; -return aligned * cpp; +if (check_mul_overflow (aligned, cpp, &pitch)) +return 0 ; +return pitch; } int radeon_mode_dumb_create(struct drm_file *file_priv,
@@ -839,8 +844,12 @@ int radeon_mode_dumb_create(struct drm_file *file_priv, args->pitch =radeon_align_pitch (rdev, args->width,DIV_ROUND_UP (args->bpp,8 ),0 ); +if (!args->pitch) +return -EINVAL ; args->size = (u64 )args->pitch * args->height; args->size =ALIGN (args->size,PAGE_SIZE ); +if (!args->size) +return -EINVAL ; r = radeon_gem_object_create(rdev, args->size, 0, RADEON_GEM_DOMAIN_VRAM, 0,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 363/1266 drm/radeon: fix memory leak in radeon_ring_restore() on lock failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 82f1d6042611d45b8b9de423bbcb4e0ced9ec62b ]
radeon_ring_restore() takes ownership of the data buffer allocated by radeon_ring_backup(). The caller (radeon_gpu_reset()) only frees it in the non-restore branch; in the restore branch it relies on radeon_ring_restore() to free it.
If radeon_ring_lock() fails, the function returned early without calling kvfree(data), leaking the ring backup buffer on every GPU reset that fails at the lock stage. During repeated GPU resets this causes cumulative kernel memory exhaustion.
Free data before returning the error.
--- drivers/gpu/drm/radeon/radeon_ring.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/radeon/radeon_ring.c +3 -1
@@ -354,8 +354,10 @@ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,/* restore the saved ring content */ r =radeon_ring_lock (rdev, ring, size); -if (r) +if (r) { +kvfree (data);return r; + }for (i =0 ; i < size; ++i) {radeon_ring_write (ring, data[i]);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 364/1266 libbpf: Report error when a negative kprobe offset is specified
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aaron Tomlin <[email protected]>
[ Upstream commit ad35d8018669fd2eea76e3f74eb050fd3d2fb690 ]
In attach_kprobe(), the parsing logic uses sscanf() to extract the target function name and offset from the section definition. Currently, if a user specifies a negative offset (e.g., SEC("kprobe/func+-100")), the input is not explicitly caught and reported as an error.
This commit updates the logic to explicitly notify the user when a negative integer is provided. To facilitate this check, the offset variable is changed from unsigned long to long so that sscanf() can accurately capture a negative input for evaluation.
If a negative offset is detected, the loader will now print an informative warning stating that the offset must be non-negative, and return -EINVAL.
Additionally, free(func) is called in this new error path to prevent a memory leak, as the function name string is dynamically allocated by sscanf().
--- tools/lib/bpf/libbpf.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
tools/lib/bpf/libbpf.c +8 -1
@@ -10926,7 +10926,7 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,static int attach_kprobe (const struct bpf_program *prog,long cookie,struct bpf_link **link) {DECLARE_LIBBPF_OPTS (bpf_kprobe_opts, opts); -unsigned long offset =0 ; +long offset =0 ;const char *func_name;char *func;int n;
@@ -10948,6 +10948,13 @@ static int attach_kprobe(const struct bpf_program *prog, long cookie, struct bpfpr_warn ("kprobe name is invalid: %s\n" , func_name);return -EINVAL ; } + +if (offset <0 ) { +free (func); +pr_warn ("kprobe offset must be a non-negative integer: %li\n" , offset); +return -EINVAL ; + } +if (opts.retprobe && offset !=0 ) {free (func);pr_warn ("kretprobes do not support offset specification\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 365/1266 Documentation: proc: fix section numbering in table of contents
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baolin Liu <[email protected]>
[ Upstream commit 97a7bd8c2c58a6d820df563d1d0f68aafec45477 ]
Commit e24ccaaf7ec4 ("block: remove last remaining traces of IDE documentation") removed the IDE section but left its table of contents entry behind.
Fix the stale entry and renumber the following sections.
Message-ID: <[email protected]>
--- Documentation/filesystems/proc.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
Documentation/filesystems/proc.rst +7 -7
@@ -23,13 +23,13 @@ fixes/update part 1.1 Stefani Seibold <[email protected]> June 9 2009 1 Collecting System Information 1.1 Process-Specific Subdirectories 1.2 Kernel data - 1.3 IDE devices in /proc/ide - 1.4 Networking info in /proc/net - 1.5 SCSI info - 1.6 Parallel port info in /proc/parport - 1.7 TTY info in /proc/tty - 1.8 Miscellaneous kernel statistics in /proc/stat - 1.9 Ext4 file system parameters + 1.3 Networking info in /proc/net + 1.4 SCSI info + 1.5 Parallel port info in /proc/parport + 1.6 TTY info in /proc/tty + 1.7 Miscellaneous kernel statistics in /proc/stat + 1.8 Ext4 file system parameters + 1.9 /proc/consoles - Shows registered system consoles 2 Modifying System Parameters
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 366/1266 arm64: dts: rockchip: Fix gmac0 reset pin for NanoPi R5S
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Diederik de Haas <[email protected]>
[ Upstream commit c83c4a09d4c01c91d6c52d6d4d77a06892a3e83b ]
According to the NanoPi R5S 2204 schematic on page 6, GPIO0_C4 is for GMAC0_INT/PMEB_GPIO0_C4, while GPIO0_C5 is for GMAC0_RSTn_GPIO0_C5. While the 'reset-gpios' property was set correctly, the corresponding pinctrl didn't match that.
Next to fixing the pinctrl definition, also change the node name and phandle to match what is used in the schematic.
--- arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts +3 -3
@@ -77,7 +77,7 @@ &mdio0 { rgmii_phy0: ethernet-phy@1 { compatible = "ethernet-phy-ieee802.3-c22"; reg = <1>; - pinctrl-0 = <ð_phy0_reset_pin>; + pinctrl-0 = <&gmac0_rstn_gpio0_c5_pin>; pinctrl-names = "default"; }; };
@@ -111,8 +111,8 @@ &pcie3x2 { &pinctrl { gmac0 { - eth_phy0_reset_pin: eth-phy0-reset-pin { - rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>; + gmac0_rstn_gpio0_c5_pin: gmac0-rstn-gpio0-c5-pin { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 367/1266 arm64: dts: qcom: sdm845-mezzanine: Fix camss ports unit_address_vs_reg warning
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit f20a82aacd7f381084391a8d1f0f58defa91974c ]
Add necessary properties for ports node in SDM845 DB845c Navigation mezzanine overlay to fix W=1 DTC warning:
sdm845-db845c-navigation-mezzanine.dtso:19.10-24.5: Warning (unit_address_vs_reg): /fragment@0/__overlay__/ports/port@0: node has a unit name, but no reg or ranges property
--- .../boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso | 5 +++++ 1 file changed, 5 insertions(+)
arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso +5 -0
@@ -16,7 +16,12 @@ status = "okay"; ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + csiphy0_ep: endpoint { data-lanes = <0 1 2 3>; remote-endpoint = <&ov8856_ep>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 368/1266 wifi: cfg80211: fix grammar in MLO group key error message
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Louis Kotze <[email protected]>
[ Upstream commit 9dcc1af3bbf5441f71a1e51b8d81bdf38a249607 ]
The error message emitted by nl80211_validate_key_link_id() when a group key install on an MLO wdev is missing the link ID reads "link ID must for MLO group key", which is missing the words "be set". This makes the error harder to grep and parse in userspace logs, and is reported verbatim by wpa_supplicant via its nl80211 extack relay, e.g.:
wpa_supplicant: nl80211: kernel reports: link ID must for MLO group key
The sibling error strings in the same helper already use grammatical phrasing ("link ID not allowed for pairwise key", "invalid link ID for MLO group key", "link ID not allowed for non-MLO group key"). Fix this one to match.
No functional change.
--- net/wireless/nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/wireless/nl80211.c +1 -1
@@ -4456,7 +4456,7 @@ static int nl80211_validate_key_link_id(struct genl_info *info,if (wdev->valid_links) {if (link_id ==-1 ) {GENL_SET_ERR_MSG (info, -"link ID must for MLO group key" ); +"link ID must be set for MLO group key" );return -EINVAL ; }if (!(wdev->valid_links &BIT (link_id))) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 369/1266 arm64: tegra: Fix Tegra234 MGBE PTP clock
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jon Hunter <[email protected]>
[ Upstream commit 8f0cc929a4bad534c5a860a53d88912cf16d9c9c ]
The Tegra MGBE PTP clock is incorrectly named as 'ptp-ref' and not 'ptp_ref' and this causing the initialisation of the PTP clock to fail. The device-tree binding doc for the device and the Tegra MGBE driver have been updated to use the correct name and so update the device-tree for Tegra234 as well.
--- arch/arm64/boot/dts/nvidia/tegra234.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/nvidia/tegra234.dtsi +4 -4
@@ -1447,7 +1447,7 @@ ethernet@6800000 { <&bpmp TEGRA234_CLK_MGBE0_RX_PCS_M>, <&bpmp TEGRA234_CLK_MGBE0_RX_PCS>, <&bpmp TEGRA234_CLK_MGBE0_TX_PCS>; - clock-names = "mgbe", "mac", "mac-divider", "ptp-ref", "rx-input-m", + clock-names = "mgbe", "mac", "mac-divider", "ptp_ref", "rx-input-m", "rx-input", "tx", "eee-pcs", "rx-pcs-input", "rx-pcs-m", "rx-pcs", "tx-pcs"; resets = <&bpmp TEGRA234_RESET_MGBE0_MAC>,
@@ -1481,7 +1481,7 @@ ethernet@6900000 { <&bpmp TEGRA234_CLK_MGBE1_RX_PCS_M>, <&bpmp TEGRA234_CLK_MGBE1_RX_PCS>, <&bpmp TEGRA234_CLK_MGBE1_TX_PCS>; - clock-names = "mgbe", "mac", "mac-divider", "ptp-ref", "rx-input-m", + clock-names = "mgbe", "mac", "mac-divider", "ptp_ref", "rx-input-m", "rx-input", "tx", "eee-pcs", "rx-pcs-input", "rx-pcs-m", "rx-pcs", "tx-pcs"; resets = <&bpmp TEGRA234_RESET_MGBE1_MAC>,
@@ -1515,7 +1515,7 @@ ethernet@6a00000 { <&bpmp TEGRA234_CLK_MGBE2_RX_PCS_M>, <&bpmp TEGRA234_CLK_MGBE2_RX_PCS>, <&bpmp TEGRA234_CLK_MGBE2_TX_PCS>; - clock-names = "mgbe", "mac", "mac-divider", "ptp-ref", "rx-input-m", + clock-names = "mgbe", "mac", "mac-divider", "ptp_ref", "rx-input-m", "rx-input", "tx", "eee-pcs", "rx-pcs-input", "rx-pcs-m", "rx-pcs", "tx-pcs"; resets = <&bpmp TEGRA234_RESET_MGBE2_MAC>,
@@ -1549,7 +1549,7 @@ ethernet@6b00000 { <&bpmp TEGRA234_CLK_MGBE3_RX_PCS_M>, <&bpmp TEGRA234_CLK_MGBE3_RX_PCS>, <&bpmp TEGRA234_CLK_MGBE3_TX_PCS>; - clock-names = "mgbe", "mac", "mac-divider", "ptp-ref", "rx-input-m", + clock-names = "mgbe", "mac", "mac-divider", "ptp_ref", "rx-input-m", "rx-input", "tx", "eee-pcs", "rx-pcs-input", "rx-pcs-m", "rx-pcs", "tx-pcs"; resets = <&bpmp TEGRA234_RESET_MGBE3_MAC>,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 370/1266 dt-bindings: pinctrl: nvidia,tegra234: Add missing required block
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 61b5deb5a968f7a82124f9b2591a6a151ed7273a ]
Binding should require 'reg' property, because address space cannot be missing in the hardware and is already needed by the Linux drivers. Require also 'compatible' by convention, although it is not strictly necessary.
--- .../bindings/pinctrl/nvidia,tegra234-pinmux-aon.yaml | 4 ++++ .../devicetree/bindings/pinctrl/nvidia,tegra234-pinmux.yaml | 4 ++++ 2 files changed, 8 insertions(+)
Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux-aon.yaml +4 -0
@@ -55,6 +55,10 @@ patternProperties: drive_soc_gpio27_pee6, drive_ao_retention_n_pee2, drive_vcomp_alert_pee1, drive_hdmi_cec_pgg0 ] +required: + - compatible + - reg + unevaluatedProperties: false examples:
Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux.yaml +4 -0
@@ -112,6 +112,10 @@ patternProperties: drive_sdmmc1_dat2_pj4, drive_sdmmc1_dat1_pj3, drive_sdmmc1_dat0_pj2 ] +required: + - compatible + - reg + unevaluatedProperties: false examples:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 371/1266 drm/amdkfd: Validate CRIU-restored IDs before idr_alloc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit 85043dd49c2f51a37b22618168e3ae59ab92f0d6 ]
The KFD CRIU restore flow restores previously saved object IDs from userspace.
For event restore:
kfd_criu_restore_event()
-> create_signal_event() / create_other_event()
-> allocate_event_notification_slot()
-> idr_alloc(..., *restore_id, *restore_id + 1, ...)For BO restore:
criu_restore_memory_of_gpu()
-> idr_alloc(..., bo_priv->idr_handle, ...)
In both cases, the restored ID comes from userspace-provided CRIU data.
idr_alloc() expects the ID range values to fit within signed int limits. If a restored ID is larger than INT_MAX, it can trigger a WARN in the IDR layer.
A kernel WARN is undesirable because it prints a warning trace and may cause a panic or reboot on systems with panic_on_warn enabled.
Smatch reported these paths as allowing unchecked userspace values to reach idr_alloc().
Add INT_MAX validation before using restored IDs in:
- kfd_criu_restore_event()
- criu_restore_memory_of_gpu()
If the restored ID is invalid, return -EINVAL.
This prevents invalid restore data from reaching the IDR layer and avoids WARN-triggering paths, while keeping valid restore behavior unchanged.
--- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 3 +++ drivers/gpu/drm/amd/amdkfd/kfd_events.c | 5 +++++ 2 files changed, 8 insertions(+)
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +3 -0
@@ -2327,6 +2327,9 @@ static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd,const bool criu_resume = true;u64 offset; +if (bo_priv->idr_handle >INT_MAX ) +return -EINVAL ; +if (bo_bucket->alloc_flags &KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL ) {if (bo_bucket->size !=kfd_doorbell_process_slice (pdd->dev->kfd))
drivers/gpu/drm/amd/amdkfd/kfd_events.c +5 -0
@@ -479,6 +479,11 @@ int kfd_criu_restore_event(struct file *devkfd, } *priv_data_offset +=sizeof (*ev_priv); +if (ev_priv->event_id >INT_MAX ) { + ret = -EINVAL ; + goto exit; + } +if (ev_priv->user_handle) { ret =kfd_kmap_event_page (p, ev_priv->user_handle);if (ret)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 372/1266 driver core: use READ_ONCE() for dev->driver in dev_has_sync_state()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich <[email protected]>
[ Upstream commit e9506871a8ea304cde48ff4a57226df2aadddae3 ]
dev_has_sync_state() reads dev->driver twice without holding device_lock() -- once for the NULL check and once to dereference ->sync_state. Some callers only hold device_links_write_lock, which doesn't prevent a concurrent unbind from clearing dev->driver via device_unbind_cleanup().
Fix it by reading dev->driver exactly once with READ_ONCE(), pairing with the WRITE_ONCE() in device_set_driver().
--- include/linux/device.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
include/linux/device.h +4 -1
@@ -1125,9 +1125,12 @@ static inline struct device_node *dev_of_node(struct device *dev)static inline bool dev_has_sync_state (struct device *dev) { +struct device_driver *drv; +if (!dev)return false; -if (dev->driver && dev->driver->sync_state) + drv =READ_ONCE (dev->driver); +if (drv && drv->sync_state)return true;if (dev->bus && dev->bus->sync_state)return true;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 373/1266 wifi: rtw89: Correct data type for scan index to avoid infinite loop
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shin-Yi Lin <[email protected]>
[ Upstream commit 08fdcb529df6df3562dd2b0035f88dd5be8b3c68 ]
A kernel soft lockup was observed during Wi-Fi scanning on the 6GHz band. The CPU becomes stuck in rtw89_hw_scan_add_chan_ax for over 20 seconds, leading to a system panic.
RIP points to 0f b6 c3 (movzbl %bl, %eax), which zero-extends the low 8 bits of RBX into RAX.
RBX (the counter i) has reached a huge value: 0x137466a1.
watchdog: BUG: soft lockup - CPU#2 stuck for 26s! [kworker/u16:4:6124] Workqueue: events_unbound cfg80211_wiphy_work [cfg80211] RIP: 0010:rtw89_hw_scan_add_chan_ax+0xb3/0x6e0 [rtw89_core] Code: a0 48 89 45 a8 44 89 6d 9c 44 89 75 98 eb 29 66 66 2e 0f 1f 84 00 00 00 00 00 66 66 2e 0f 1f 84 00 00 00 00 00 66 90 83 c3 01 <0f> b6 c3 41 3b 44 24 74 0f 83 0b 02 00 00 0f b6 c3 48 8d 14 80 49 RSP: 0018:ffffcb48cbaa39f8 EFLAGS: 00000202 RAX: 0000000000000005 RBX: 00000000137466a1 RCX: 0000000000000000 RDX: ffff89ffc9d851a8 RSI: 0000000000004f0d RDI: 0000000096af0130 RBP: ffffcb48cbaa3a60 R08: 0000000000000000 R09: ffff8a00b7502080 R10: ffff8a00b75ff600 R11: 0000000000000000 R12: ffff89ffc7553870 R13: ffff8a00b7ac8f19 R14: ffff8a00b75020d8 R15: ffff89ffc3d54d80 FS: 0000000000000000(0000) GS:ffff8a014f962000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007558d7f9f4c4 CR3: 0000000178040001 CR4: 00000000001706f0 Call Trace: <TASK> rtw89_hw_scan_prep_chan_list_ax+0x8a/0x400 [rtw89_core] rtw89_hw_scan_start+0x546/0x8a0 [rtw89_core] ? rtw89_fw_h2c_default_cmac_tbl+0x13c/0x1f0 [rtw89_core] rtw89_ops_hw_scan+0xae/0x120 [rtw89_core] drv_hw_scan+0xbb/0x180 [mac80211] __ieee80211_start_scan+0x2fc/0x750 [mac80211] ieee80211_request_scan+0xe/0x20 [mac80211] ieee80211_scan+0x123/0x190 [mac80211] rdev_scan+0x40/0x110 [cfg80211] cfg80211_scan_6ghz+0x5a1/0xa30 [cfg80211]
By objdump with source:
for (i = 0; i < req->n_6ghz_params; i++) { 5fbc0: 83 c3 01 add $0x1,%ebx --> i++
5fbc3: 0f b6 c3 movzbl %bl,%eax --> get counter
fbc6: 41 3b 44 24 74 cmp 0x74(%r12),%eax
* RBX: 00000000137466a1 -> %bl = a1 -> EAX = 000000a1 (161)
--- drivers/net/wireless/realtek/rtw89/fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/fw.c +1 -1
@@ -3641,7 +3641,7 @@ static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev,struct sk_buff *skb;bool found;int ret =0 ; -u8 i; +u32 i;if (!req->n_6ghz_params)return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 374/1266 wifi: rtw88: fix OOB read from firmware RX descriptor exceeding DMA buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 6e76e9ed273dfb4b3333a5ebbb94958cc5752ab6 ]
In rtw_pci_rx_napi(), new_len is computed as the sum of pkt_len (14-bit descriptor field, max 16383) and pkt_offset (drv_info_sz + shift, both firmware-controlled). The result can exceed RTK_PCI_RX_BUF_SIZE (11478), causing an out-of-bounds read from the pre-allocated DMA buffer when skb_put_data copies new_len bytes. The USB transport already validates this (rtw_usb_rx_data_put checks against RTW_USB_MAX_RECVBUF_SZ); the PCIe path does not.
Add a check that new_len does not exceed the DMA buffer size.
--- drivers/net/wireless/realtek/rtw88/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/wireless/realtek/rtw88/pci.c +5 -0
@@ -1074,6 +1074,11 @@ static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,* discard the frame if none available */ new_len = pkt_stat.pkt_len + pkt_offset; +if (unlikely (new_len >RTK_PCI_RX_BUF_SIZE )) { +rtw_dbg (rtwdev,RTW_DBG_RX , +"oversized RX packet: %u\n" , new_len); + goto next_rp; + } new =dev_alloc_skb (new_len);if (WARN_ONCE (!new,"rx routine starvation\n" )) goto next_rp;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 375/1266 kconfig: fix potential NULL pointer dereference in conf_askvalue
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xingjing Deng <[email protected]>
[ Upstream commit b9d21c32dca2167a614e66c9e27999b9e1c33d55 ]
In conf_askvalue(), the 'def' argument (retrieved via sym_get_string_value) can be NULL. While current call sites ensure that 'def' is valid, calling printf("%s\n", def) is technically undefined behavior and could lead to a segmentation fault on certain libc implementations if the function were called with a NULL pointer in the future.
Improve the robustness of conf_askvalue() by providing an empty string as a fallback.
Additionally, remove the redundant re-initialization of the 'line' buffer inside the !sym_is_changeable(sym) block, as it is already properly initialized at the function entry.
--- scripts/kconfig/conf.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
scripts/kconfig/conf.c +2 -4
@@ -323,9 +323,7 @@ static int conf_askvalue(struct symbol *sym, const char *def) line[1 ] =0 ;if (!sym_is_changeable (sym)) { -printf ("%s\n" , def); - line[0 ] ='\n' ; - line[1 ] =0 ; +printf ("%s\n" , def ?:"" );return 0 ; }
@@ -333,7 +331,7 @@ static int conf_askvalue(struct symbol *sym, const char *def)case oldconfig:case syncconfig:if (sym_has_value (sym)) { -printf ("%s\n" , def); +printf ("%s\n" , def ?:"" );return 0 ; }/* fall through */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 376/1266 wifi: ath9k: fix OOB access from firmware tx status queue ID
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 7ce2f118a2389e8f0a64068c6fe7cc7d40639be0 ]
ath_tx_edma_tasklet() accesses sc->tx.txq[ts.qid] where ts.qid is a 4-bit hardware field (0-15), but the txq array only has ATH9K_NUM_TX_QUEUES (10) entries. A qid >= 10 causes an OOB array access.
Add a bounds check on ts.qid before using it as an array index.
--- drivers/net/wireless/ath/ath9k/xmit.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/wireless/ath/ath9k/xmit.c +5 -0
@@ -2754,6 +2754,11 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)continue ; } +if (ts.qid >=ATH9K_NUM_TX_QUEUES ) { +ath_dbg (common,XMIT ,"invalid qid %d\n" , ts.qid); +continue ; + } + txq = &sc->tx.txq[ts.qid];ath_txq_lock (sc, txq);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 377/1266 ARM: dts: am335x-sl50: Fix audio bitclock and frame master endpoint
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jihed Chaibi <[email protected]>
[ Upstream commit 2bc564f46b00dc4f4331fc337277ff3f5fac8a4e ]
The cpu_endpoint in mcasp0 specifies the TLV320AIC3106 codec as the bitclock and frame master, but the phandles point to the codec's port node (codec_port) rather than its endpoint node (codec_endpoint).
audio-graph-card calls simple_util_parse_daifmt() with ep_codec set to the endpoint node (codec_endpoint). The function resolves the bitclock-master phandle and checks whether it equals ep_codec. Since codec_port is the parent of codec_endpoint, not the endpoint itself, the comparison always evaluates to false. This causes the mcasp0 CPU side to be silently configured as bitclock and frame master instead of the codec, which is the opposite of the intended configuration.
Fix by pointing bitclock-master and frame-master to codec_endpoint.
--- arch/arm/boot/dts/ti/omap/am335x-sl50.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/boot/dts/ti/omap/am335x-sl50.dts +2 -2
@@ -557,8 +557,8 @@ cpu_endpoint: endpoint { remote-endpoint = <&codec_endpoint>; dai-format = "dsp_b"; - bitclock-master = <&codec_port>; - frame-master = <&codec_port>; + bitclock-master = <&codec_endpoint>; + frame-master = <&codec_endpoint>; bitclock-inversion; clocks = <&audio_mclk>; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 378/1266 watchdog: sp5100_tco: Use EFCH MMIO for newer Hygon FCH
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yingjie Gao <[email protected]>
[ Upstream commit 4f675f036cd5e9cfbe6df5f24f8338158af96a4b ]
Commit 009637de1f65 ("watchdog: sp5100_tco: support Hygon FCH/SCH (Server Controller Hub)") added Hygon vendor matching to the efch layout selection, but newer Hygon 0x790b SMBus devices still need the efch_mmio path.
The efch_mmio path enables EFCH_PM_DECODEEN_WDT_TMREN before probing the watchdog MMIO block. If firmware leaves that bit clear and the driver picks the legacy efch path instead, probe falls back to the alternate window and fails with "Watchdog hardware is disabled".
Select efch_mmio for Hygon 0x790b devices with revision 0x51 or later, matching the equivalent AMD behavior and allowing the watchdog to initialize on those systems.
--- drivers/watchdog/sp5100_tco.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/watchdog/sp5100_tco.c +2 -1
@@ -92,7 +92,8 @@ static enum tco_reg_layout tco_reg_layout(struct pci_dev *dev) dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && dev->revision < 0x40) {return sp5100; - } else if (dev->vendor == PCI_VENDOR_ID_AMD && + } else if ((dev->vendor == PCI_VENDOR_ID_AMD || + dev->vendor == PCI_VENDOR_ID_HYGON) && sp5100_tco_pci->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS && sp5100_tco_pci->revision >= AMD_ZEN_SMBUS_PCI_REV) {return efch_mmio;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 379/1266 watchdog: sama5d4_wdt: Fix WDDIS detection on SAM9X60 and SAMA7G5
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Balakrishnan Sambath <[email protected]>
[ Upstream commit e8bc610b14a99d24b0916635102cc52ba41def9b ]
The driver hardcoded AT91_WDT_WDDIS (bit 15) in wdt_enabled and the probe initial state readout. SAM9X60 and SAMA7G5 use bit 12 (AT91_SAM9X60_WDDIS), causing incorrect WDDIS detection.
Introduce a per-device wddis_mask field to select the correct WDDIS bit based on the compatible string.
--- drivers/watchdog/sama5d4_wdt.c | 48 +++++++++++++++------------------- 1 file changed, 21 insertions(+), 27 deletions(-)
drivers/watchdog/sama5d4_wdt.c +21 -27
@@ -30,6 +30,7 @@ struct sama5d4_wdt {void __iomem *reg_base;u32 mr;u32 ir; +u32 wddis_mask;unsigned long last_ping;bool need_irq;bool sam9x60_support;
@@ -48,7 +49,10 @@ MODULE_PARM_DESC(nowayout,"Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -#define wdt_enabled (!(wdt->mr & AT91_WDT_WDDIS)) +static inline bool wdt_enabled (struct sama5d4_wdt *wdt) +{ +return !(wdt->mr & wdt->wddis_mask); +}#define wdt_read (wdt, field) \ readl_relaxed((wdt)->reg_base + (field))
@@ -81,12 +85,9 @@ static int sama5d4_wdt_start(struct watchdog_device *wdd) {struct sama5d4_wdt *wdt =watchdog_get_drvdata (wdd); -if (wdt->sam9x60_support) { +if (wdt->sam9x60_support)writel_relaxed (wdt->ir, wdt->reg_base +AT91_SAM9X60_IER ); - wdt->mr &= ~AT91_SAM9X60_WDDIS ; - }else { - wdt->mr &= ~AT91_WDT_WDDIS ; - } + wdt->mr &= ~wdt->wddis_mask;wdt_write (wdt,AT91_WDT_MR , wdt->mr);return 0 ;
@@ -96,12 +97,9 @@ static int sama5d4_wdt_stop(struct watchdog_device *wdd) {struct sama5d4_wdt *wdt =watchdog_get_drvdata (wdd); -if (wdt->sam9x60_support) { +if (wdt->sam9x60_support)writel_relaxed (wdt->ir, wdt->reg_base +AT91_SAM9X60_IDR ); - wdt->mr |=AT91_SAM9X60_WDDIS ; - }else { - wdt->mr |=AT91_WDT_WDDIS ; - } + wdt->mr |= wdt->wddis_mask;wdt_write (wdt,AT91_WDT_MR , wdt->mr);return 0 ;
@@ -117,7 +115,7 @@ static int sama5d4_wdt_ping(struct watchdog_device *wdd) }static int sama5d4_wdt_set_timeout (struct watchdog_device *wdd, -unsigned int timeout) +unsigned int timeout) {struct sama5d4_wdt *wdt =watchdog_get_drvdata (wdd);u32 value =WDT_SEC2TICKS (timeout);
@@ -140,8 +138,8 @@ static int sama5d4_wdt_set_timeout(struct watchdog_device *wdd,* If the watchdog is enabled, then the timeout can be updated. Else, * wait that the user enables it. */ -if (wdt_enabled) -wdt_write (wdt,AT91_WDT_MR , wdt->mr & ~AT91_WDT_WDDIS ); +if (wdt_enabled (wdt)) +wdt_write (wdt,AT91_WDT_MR , wdt->mr & ~wdt->wddis_mask); wdd->timeout = timeout;
@@ -184,10 +182,7 @@ static int of_sama5d4_wdt_init(struct device_node *np, struct sama5d4_wdt *wdt) {const char *tmp; -if (wdt->sam9x60_support) - wdt->mr =AT91_SAM9X60_WDDIS ; -else - wdt->mr =AT91_WDT_WDDIS ; + wdt->mr = wdt->wddis_mask;if (!of_property_read_string (np,"atmel,watchdog-type" , &tmp) && !strcmp (tmp,"software" ))
@@ -213,15 +208,11 @@ static int sama5d4_wdt_init(struct sama5d4_wdt *wdt)* If the watchdog is already running, we can safely update it. * Else, we have to disable it properly. */ -if (!wdt_enabled) { +if (!wdt_enabled (wdt)) { reg =wdt_read (wdt,AT91_WDT_MR ); -if (wdt->sam9x60_support && (!(reg &AT91_SAM9X60_WDDIS ))) -wdt_write_nosleep (wdt,AT91_WDT_MR , - reg |AT91_SAM9X60_WDDIS ); -else if (!wdt->sam9x60_support && - (!(reg &AT91_WDT_WDDIS ))) +if (!(reg & wdt->wddis_mask))wdt_write_nosleep (wdt,AT91_WDT_MR , - reg |AT91_WDT_WDDIS ); + reg | wdt->wddis_mask); }if (wdt->sam9x60_support) {
@@ -273,6 +264,9 @@ static int sama5d4_wdt_probe(struct platform_device *pdev) of_device_is_compatible(dev->of_node, "microchip,sama7g5-wdt")) wdt->sam9x60_support = true; + wdt->wddis_mask = wdt->sam9x60_support ?AT91_SAM9X60_WDDIS + :AT91_WDT_WDDIS ; +watchdog_set_drvdata (wdd, wdt); regs =devm_platform_ioremap_resource (pdev,0 );
@@ -306,8 +300,8 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)watchdog_init_timeout (wdd, wdt_timeout, dev); reg =wdt_read (wdt,AT91_WDT_MR ); -if (!(reg &AT91_WDT_WDDIS )) { - wdt->mr &= ~AT91_WDT_WDDIS ; +if (!(reg & wdt->wddis_mask)) { + wdt->mr &= ~wdt->wddis_mask;set_bit (WDOG_HW_RUNNING , &wdd->status); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 380/1266 watchdog: sprd_wdt: Remove redundant sprd_wdt_disable() on register failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 96b3cfc3b8ad0524d12fed1e08bc5df3ff345f64 ]
The driver uses devm_add_action_or_reset() to register sprd_wdt_disable() as a managed cleanup action.
When devm_watchdog_register_device() fails, the devm core will invoke the cleanup action automatically.
The explicit sprd_wdt_disable() call in the error path is therefore redundant and results in adouble cleanup.
--- drivers/watchdog/sprd_wdt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/watchdog/sprd_wdt.c +2 -3
@@ -320,10 +320,9 @@ static int sprd_wdt_probe(struct platform_device *pdev)watchdog_init_timeout (&wdt->wdd,0 , dev); ret =devm_watchdog_register_device (dev, &wdt->wdd); -if (ret) { -sprd_wdt_disable (wdt); +if (ret)return ret; - } +platform_set_drvdata (pdev, wdt);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 381/1266 media: cedrus: Fix failure to clean up hardware on probe failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Holland <[email protected]>
[ Upstream commit f0a22f1d602ed499a192284de5e811a73421f0c7 ]
If V4L2 device fails to register, then SRAM still be claimed and as a result driver will not be able to probe again.
cedrus 1c0e000.video-codec: Failed to claim SRAM
cedrus 1c0e000.video-codec: Failed to probe hardware
cedrus 1c0e000.video-codec: probe with driver cedrus failed with error -16
cedrus_hw_remove undoes everything that was previously done by cedrus_hw_probe, such as disabling runtime power management and releasing the claimed SRAM and reserved memory region.
--- drivers/staging/media/sunxi/cedrus/cedrus.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/staging/media/sunxi/cedrus/cedrus.c +3 -1
@@ -478,7 +478,7 @@ static int cedrus_probe(struct platform_device *pdev) ret =v4l2_device_register (&pdev->dev, &dev->v4l2_dev);if (ret) {dev_err (&pdev->dev,"Failed to register V4L2 device\n" ); -return ret; + goto err_hw; } vfd = &dev->vfd;
@@ -539,6 +539,8 @@ static int cedrus_probe(struct platform_device *pdev)v4l2_m2m_release (dev->m2m_dev); err_v4l2:v4l2_device_unregister (&dev->v4l2_dev); +err_hw: +cedrus_hw_remove (dev);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 382/1266 media: v4l2-common: Add YUV24 format info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nas Chung <[email protected]>
[ Upstream commit 968b741872914a15363af0daf24ed2e82ec355f3 ]
The YUV24 format is missing an entry in the v4l2_format_info(). The YUV24 format is the packed YUV 4:4:4 formats with 8 bits per component.
--- drivers/media/v4l2-core/v4l2-common.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/v4l2-core/v4l2-common.c +1 -0
@@ -262,6 +262,7 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_MT2110T, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2, .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }}, { .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 383/1266 pinctrl: sunxi: fix regulator leak in sunxi_pmx_request() error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 334f7bcbdc79dc8e5b938ac3372453a5368221cf ]
In the error path of sunxi_pmx_request(), the code calls regulator_put(s_reg->regulator) to release the regulator. However, s_reg->regulator is only assigned after a successful regulator_enable(). This causes a memory leak: the regulator obtained via regulator_get() is never properly released when regulator_enable() fails.
--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/sunxi/pinctrl-sunxi.c +1 -1
@@ -880,7 +880,7 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)return 0 ; out: -regulator_put (s_reg->regulator); +regulator_put (reg);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 384/1266 arm64: dts: rockchip: fix rk809 interrupt pin on rk3566-roc-pc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weixin Guo <[email protected]>
[ Upstream commit 460bac478c5fe69054ffc60d607bba03bcaf909b ]
The RK809 PMIC interrupt pin on the Firefly ROC-RK3566-PC (Station M2) is physically connected to GPIO0_A3 (RK_PA3) according to the board's schematic.
Currently, the PMIC node incorrectly specifies RK_PA7 for the interrupt, which prevents the PMIC from correctly signaling interrupts. (Note that the pinctrl node 'pmic_int' correctly configures RK_PA3).
Fix this by updating the interrupts property to use RK_PA3.
--- arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts +1 -1
@@ -244,7 +244,7 @@ rk809: pmic@20 { compatible = "rockchip,rk809"; reg = <0x20>; interrupt-parent = <&gpio0>; - interrupts = <RK_PA7 IRQ_TYPE_LEVEL_LOW>; + interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>; clock-output-names = "rk808-clkout1", "rk808-clkout2"; assigned-clocks = <&cru I2S1_MCLKOUT_TX>; assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 385/1266 arm64: dts: imx8x-colibri: Correct SODIMM PAD settings
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peng Fan <[email protected]>
[ Upstream commit 0a03ee38a262cab0d9754e9947d565e089a9f7a5 ]
SION is BIT(30), not BIT(26). Correct it.
--- arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi +2 -2
@@ -383,12 +383,12 @@ pinctrl_adc0: adc0grp { */ pinctrl_atmel_adap: atmeladaptergrp { fsl,pins = <IMX8QXP_UART1_RX_LSIO_GPIO0_IO22 0x21>, /* SODIMM 30 */ - <IMX8QXP_UART1_TX_LSIO_GPIO0_IO21 0x4000021>; /* SODIMM 28 */ + <IMX8QXP_UART1_TX_LSIO_GPIO0_IO21 0x40000021>; /* SODIMM 28 */ }; /* Atmel MXT touchsceen + boards with built-in Capacitive Touch Connector */ pinctrl_atmel_conn: atmelconnectorgrp { - fsl,pins = <IMX8QXP_QSPI0B_DATA2_LSIO_GPIO3_IO20 0x4000021>, /* SODIMM 107 */ + fsl,pins = <IMX8QXP_QSPI0B_DATA2_LSIO_GPIO3_IO20 0x40000021>, /* SODIMM 107 */ <IMX8QXP_QSPI0B_SS1_B_LSIO_GPIO3_IO24 0x21>; /* SODIMM 106 */ };
Signature · 1 line
2.53.0