commit: 0d6ea46e3e6783a7f13b4a75e254ae727414acbc Author: Alice Ferrazzi <alicef <AT> gentoo <DOT> org> AuthorDate: Wed Dec 21 18:45:57 2022 +0000 Commit: Alice Ferrazzi <alicef <AT> gentoo <DOT> org> CommitDate: Wed Dec 21 18:46:42 2022 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=0d6ea46e
Linux patch 6.0.15 Signed-off-by: Alice Ferrazzi <alicef <AT> gentoo.org> 0000_README | 4 + 1014_linux-6.0.15.patch | 1127 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1131 insertions(+) diff --git a/0000_README b/0000_README index 578f9e3d..302d8339 100644 --- a/0000_README +++ b/0000_README @@ -99,6 +99,10 @@ Patch: 1013_linux-6.0.14.patch From: http://www.kernel.org Desc: Linux 6.0.14 +Patch: 1014_linux-6.0.15.patch +From: http://www.kernel.org +Desc: Linux 6.0.15 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1014_linux-6.0.15.patch b/1014_linux-6.0.15.patch new file mode 100644 index 00000000..2173b214 --- /dev/null +++ b/1014_linux-6.0.15.patch @@ -0,0 +1,1127 @@ +diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst +index 0bfb4c3397489..9bc9db8ec6517 100644 +--- a/Documentation/security/keys/trusted-encrypted.rst ++++ b/Documentation/security/keys/trusted-encrypted.rst +@@ -350,7 +350,8 @@ Load an encrypted key "evm" from saved blob:: + + Instantiate an encrypted key "evm" using user-provided decrypted data:: + +- $ keyctl add encrypted evm "new default user:kmk 32 `cat evm_decrypted_data.blob`" @u ++ $ evmkey=$(dd if=/dev/urandom bs=1 count=32 | xxd -c32 -p) ++ $ keyctl add encrypted evm "new default user:kmk 32 $evmkey" @u + 794890253 + + $ keyctl print 794890253 +diff --git a/Makefile b/Makefile +index a3c02b45fb575..0c7ae314ad3d5 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 0 +-SUBLEVEL = 14 ++SUBLEVEL = 15 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index 2796e81d27260..ea46649b2ed3e 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -7522,7 +7522,7 @@ static void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) + { + struct e1000_hw *hw = &adapter->hw; + unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; +- u32 reg, msgbuf[3]; ++ u32 reg, msgbuf[3] = {}; + u8 *addr = (u8 *)(&msgbuf[1]); + + /* process all the same items cleared in a function level reset */ +diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c +index 14e8d04cb4347..2e9742952c4e9 100644 +--- a/drivers/net/loopback.c ++++ b/drivers/net/loopback.c +@@ -211,7 +211,7 @@ static __net_init int loopback_net_init(struct net *net) + int err; + + err = -ENOMEM; +- dev = alloc_netdev(0, "lo", NET_NAME_UNKNOWN, loopback_setup); ++ dev = alloc_netdev(0, "lo", NET_NAME_PREDICTABLE, loopback_setup); + if (!dev) + goto out; + +diff --git a/drivers/pci/controller/pcie-mt7621.c b/drivers/pci/controller/pcie-mt7621.c +index 33eb37a2225c1..0f02f191946a0 100644 +--- a/drivers/pci/controller/pcie-mt7621.c ++++ b/drivers/pci/controller/pcie-mt7621.c +@@ -471,7 +471,8 @@ static int mt7621_pcie_register_host(struct pci_host_bridge *host) + } + + static const struct soc_device_attribute mt7621_pcie_quirks_match[] = { +- { .soc_id = "mt7621", .revision = "E2" } ++ { .soc_id = "mt7621", .revision = "E2" }, ++ { /* sentinel */ } + }; + + static int mt7621_pcie_probe(struct platform_device *pdev) +diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c +index 4ee4ca09873af..9d3bbbb33dcf3 100644 +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -44,7 +44,7 @@ + #define PCI_DEVICE_ID_INTEL_ADLP 0x51ee + #define PCI_DEVICE_ID_INTEL_ADLM 0x54ee + #define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1 +-#define PCI_DEVICE_ID_INTEL_RPL 0x460e ++#define PCI_DEVICE_ID_INTEL_RPL 0xa70e + #define PCI_DEVICE_ID_INTEL_RPLS 0x7a61 + #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 + #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e +diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c +index 7ec223849d949..4d3f62d754789 100644 +--- a/drivers/usb/gadget/function/f_uvc.c ++++ b/drivers/usb/gadget/function/f_uvc.c +@@ -216,8 +216,9 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) + + memset(&v4l2_event, 0, sizeof(v4l2_event)); + v4l2_event.type = UVC_EVENT_DATA; +- uvc_event->data.length = req->actual; +- memcpy(&uvc_event->data.data, req->buf, req->actual); ++ uvc_event->data.length = min_t(unsigned int, req->actual, ++ sizeof(uvc_event->data.data)); ++ memcpy(&uvc_event->data.data, req->buf, uvc_event->data.length); + v4l2_event_queue(&uvc->vdev, &v4l2_event); + } + } +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 0a8d37c5af030..7191cacba2274 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -59,6 +59,7 @@ + #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 + #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed ++#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_PCH_XHCI 0x54ed + + #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 + #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 +@@ -246,7 +247,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + xhci->quirks |= XHCI_MISSING_CAS; + + if (pdev->vendor == PCI_VENDOR_ID_INTEL && +- pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI) ++ (pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI || ++ pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_PCH_XHCI)) + xhci->quirks |= XHCI_RESET_TO_DEFAULT; + + if (pdev->vendor == PCI_VENDOR_ID_INTEL && +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index a34957c4b64c0..0fd3a9d76beba 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -195,6 +195,8 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */ + { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */ ++ { USB_DEVICE(0x17A8, 0x0011) }, /* Kamstrup 444 MHz RF sniffer */ ++ { USB_DEVICE(0x17A8, 0x0013) }, /* Kamstrup 870 MHz RF sniffer */ + { USB_DEVICE(0x17A8, 0x0101) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Int Ant) */ + { USB_DEVICE(0x17A8, 0x0102) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Ext Ant) */ + { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ +diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c +index d9f20256a6a8e..b8cf21bec334e 100644 +--- a/drivers/usb/serial/f81232.c ++++ b/drivers/usb/serial/f81232.c +@@ -130,9 +130,6 @@ static u8 const clock_table[] = { F81232_CLK_1_846_MHZ, F81232_CLK_14_77_MHZ, + + static int calc_baud_divisor(speed_t baudrate, speed_t clockrate) + { +- if (!baudrate) +- return 0; +- + return DIV_ROUND_CLOSEST(clockrate, baudrate); + } + +@@ -498,9 +495,14 @@ static void f81232_set_baudrate(struct tty_struct *tty, + speed_t baud_list[] = { baudrate, old_baudrate, F81232_DEF_BAUDRATE }; + + for (i = 0; i < ARRAY_SIZE(baud_list); ++i) { +- idx = f81232_find_clk(baud_list[i]); ++ baudrate = baud_list[i]; ++ if (baudrate == 0) { ++ tty_encode_baud_rate(tty, 0, 0); ++ return; ++ } ++ ++ idx = f81232_find_clk(baudrate); + if (idx >= 0) { +- baudrate = baud_list[i]; + tty_encode_baud_rate(tty, baudrate, baudrate); + break; + } +diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c +index d789c1ec87b35..f331d39c3b267 100644 +--- a/drivers/usb/serial/f81534.c ++++ b/drivers/usb/serial/f81534.c +@@ -536,9 +536,6 @@ static int f81534_submit_writer(struct usb_serial_port *port, gfp_t mem_flags) + + static u32 f81534_calc_baud_divisor(u32 baudrate, u32 clockrate) + { +- if (!baudrate) +- return 0; +- + /* Round to nearest divisor */ + return DIV_ROUND_CLOSEST(clockrate, baudrate); + } +@@ -568,9 +565,14 @@ static int f81534_set_port_config(struct usb_serial_port *port, + u32 baud_list[] = {baudrate, old_baudrate, F81534_DEFAULT_BAUD_RATE}; + + for (i = 0; i < ARRAY_SIZE(baud_list); ++i) { +- idx = f81534_find_clk(baud_list[i]); ++ baudrate = baud_list[i]; ++ if (baudrate == 0) { ++ tty_encode_baud_rate(tty, 0, 0); ++ return 0; ++ } ++ ++ idx = f81534_find_clk(baudrate); + if (idx >= 0) { +- baudrate = baud_list[i]; + tty_encode_baud_rate(tty, baudrate, baudrate); + break; + } +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index c3b7f1d98e781..dee79c7d82d5c 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -255,6 +255,7 @@ static void option_instat_callback(struct urb *urb); + #define QUECTEL_PRODUCT_EP06 0x0306 + #define QUECTEL_PRODUCT_EM05G 0x030a + #define QUECTEL_PRODUCT_EM060K 0x030b ++#define QUECTEL_PRODUCT_EM05G_SG 0x0311 + #define QUECTEL_PRODUCT_EM12 0x0512 + #define QUECTEL_PRODUCT_RM500Q 0x0800 + #define QUECTEL_PRODUCT_RM520N 0x0801 +@@ -1160,6 +1161,8 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, + { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff), + .driver_info = RSVD(6) | ZLP }, ++ { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_SG, 0xff), ++ .driver_info = RSVD(6) | ZLP }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) }, +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index a7987fc764cc6..eabe519013e78 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -1270,8 +1270,9 @@ err: + return ret; + } + +-int ucsi_resume(struct ucsi *ucsi) ++static void ucsi_resume_work(struct work_struct *work) + { ++ struct ucsi *ucsi = container_of(work, struct ucsi, resume_work); + struct ucsi_connector *con; + u64 command; + int ret; +@@ -1279,15 +1280,21 @@ int ucsi_resume(struct ucsi *ucsi) + /* Restore UCSI notification enable mask after system resume */ + command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; + ret = ucsi_send_command(ucsi, command, NULL, 0); +- if (ret < 0) +- return ret; ++ if (ret < 0) { ++ dev_err(ucsi->dev, "failed to re-enable notifications (%d)\n", ret); ++ return; ++ } + + for (con = ucsi->connector; con->port; con++) { + mutex_lock(&con->lock); +- ucsi_check_connection(con); ++ ucsi_partner_task(con, ucsi_check_connection, 1, 0); + mutex_unlock(&con->lock); + } ++} + ++int ucsi_resume(struct ucsi *ucsi) ++{ ++ queue_work(system_long_wq, &ucsi->resume_work); + return 0; + } + EXPORT_SYMBOL_GPL(ucsi_resume); +@@ -1347,6 +1354,7 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) + if (!ucsi) + return ERR_PTR(-ENOMEM); + ++ INIT_WORK(&ucsi->resume_work, ucsi_resume_work); + INIT_DELAYED_WORK(&ucsi->work, ucsi_init_work); + mutex_init(&ucsi->ppm_lock); + ucsi->dev = dev; +@@ -1401,6 +1409,7 @@ void ucsi_unregister(struct ucsi *ucsi) + + /* Make sure that we are not in the middle of driver initialization */ + cancel_delayed_work_sync(&ucsi->work); ++ cancel_work_sync(&ucsi->resume_work); + + /* Disable notifications */ + ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); +diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h +index 8eb391e3e592c..c968474ee5473 100644 +--- a/drivers/usb/typec/ucsi/ucsi.h ++++ b/drivers/usb/typec/ucsi/ucsi.h +@@ -287,6 +287,7 @@ struct ucsi { + struct ucsi_capability cap; + struct ucsi_connector *connector; + ++ struct work_struct resume_work; + struct delayed_work work; + int work_count; + #define UCSI_ROLE_SWITCH_RETRY_PER_HZ 10 +diff --git a/fs/udf/inode.c b/fs/udf/inode.c +index 8d06daed549f9..b9a83820e1adf 100644 +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -439,6 +439,12 @@ static int udf_get_block(struct inode *inode, sector_t block, + iinfo->i_next_alloc_goal++; + } + ++ /* ++ * Block beyond EOF and prealloc extents? Just discard preallocation ++ * as it is not useful and complicates things. ++ */ ++ if (((loff_t)block) << inode->i_blkbits > iinfo->i_lenExtents) ++ udf_discard_prealloc(inode); + udf_clear_extent_cache(inode); + phys = inode_getblk(inode, block, &err, &new); + if (!phys) +@@ -488,8 +494,6 @@ static int udf_do_extend_file(struct inode *inode, + uint32_t add; + int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); + struct super_block *sb = inode->i_sb; +- struct kernel_lb_addr prealloc_loc = {}; +- uint32_t prealloc_len = 0; + struct udf_inode_info *iinfo; + int err; + +@@ -510,19 +514,6 @@ static int udf_do_extend_file(struct inode *inode, + ~(sb->s_blocksize - 1); + } + +- /* Last extent are just preallocated blocks? */ +- if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == +- EXT_NOT_RECORDED_ALLOCATED) { +- /* Save the extent so that we can reattach it to the end */ +- prealloc_loc = last_ext->extLocation; +- prealloc_len = last_ext->extLength; +- /* Mark the extent as a hole */ +- last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | +- (last_ext->extLength & UDF_EXTENT_LENGTH_MASK); +- last_ext->extLocation.logicalBlockNum = 0; +- last_ext->extLocation.partitionReferenceNum = 0; +- } +- + /* Can we merge with the previous extent? */ + if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == + EXT_NOT_RECORDED_NOT_ALLOCATED) { +@@ -550,7 +541,7 @@ static int udf_do_extend_file(struct inode *inode, + * more extents, we may need to enter possible following + * empty indirect extent. + */ +- if (new_block_bytes || prealloc_len) ++ if (new_block_bytes) + udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0); + } + +@@ -584,17 +575,6 @@ static int udf_do_extend_file(struct inode *inode, + } + + out: +- /* Do we have some preallocated blocks saved? */ +- if (prealloc_len) { +- err = udf_add_aext(inode, last_pos, &prealloc_loc, +- prealloc_len, 1); +- if (err) +- return err; +- last_ext->extLocation = prealloc_loc; +- last_ext->extLength = prealloc_len; +- count++; +- } +- + /* last_pos should point to the last written extent... */ + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) + last_pos->offset -= sizeof(struct short_ad); +@@ -610,13 +590,17 @@ out: + static void udf_do_extend_final_block(struct inode *inode, + struct extent_position *last_pos, + struct kernel_long_ad *last_ext, +- uint32_t final_block_len) ++ uint32_t new_elen) + { +- struct super_block *sb = inode->i_sb; + uint32_t added_bytes; + +- added_bytes = final_block_len - +- (last_ext->extLength & (sb->s_blocksize - 1)); ++ /* ++ * Extent already large enough? It may be already rounded up to block ++ * size... ++ */ ++ if (new_elen <= (last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) ++ return; ++ added_bytes = (last_ext->extLength & UDF_EXTENT_LENGTH_MASK) - new_elen; + last_ext->extLength += added_bytes; + UDF_I(inode)->i_lenExtents += added_bytes; + +@@ -633,12 +617,12 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) + int8_t etype; + struct super_block *sb = inode->i_sb; + sector_t first_block = newsize >> sb->s_blocksize_bits, offset; +- unsigned long partial_final_block; ++ loff_t new_elen; + int adsize; + struct udf_inode_info *iinfo = UDF_I(inode); + struct kernel_long_ad extent; + int err = 0; +- int within_final_block; ++ bool within_last_ext; + + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) + adsize = sizeof(struct short_ad); +@@ -647,8 +631,17 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) + else + BUG(); + ++ /* ++ * When creating hole in file, just don't bother with preserving ++ * preallocation. It likely won't be very useful anyway. ++ */ ++ udf_discard_prealloc(inode); ++ + etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); +- within_final_block = (etype != -1); ++ within_last_ext = (etype != -1); ++ /* We don't expect extents past EOF... */ ++ WARN_ON_ONCE(within_last_ext && ++ elen > ((loff_t)offset + 1) << inode->i_blkbits); + + if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || + (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { +@@ -664,19 +657,17 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) + extent.extLength |= etype << 30; + } + +- partial_final_block = newsize & (sb->s_blocksize - 1); ++ new_elen = ((loff_t)offset << inode->i_blkbits) | ++ (newsize & (sb->s_blocksize - 1)); + + /* File has extent covering the new size (could happen when extending + * inside a block)? + */ +- if (within_final_block) { ++ if (within_last_ext) { + /* Extending file within the last file block */ +- udf_do_extend_final_block(inode, &epos, &extent, +- partial_final_block); ++ udf_do_extend_final_block(inode, &epos, &extent, new_elen); + } else { +- loff_t add = ((loff_t)offset << sb->s_blocksize_bits) | +- partial_final_block; +- err = udf_do_extend_file(inode, &epos, &extent, add); ++ err = udf_do_extend_file(inode, &epos, &extent, new_elen); + } + + if (err < 0) +@@ -777,10 +768,11 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, + goto out_free; + } + +- /* Are we beyond EOF? */ ++ /* Are we beyond EOF and preallocated extent? */ + if (etype == -1) { + int ret; + loff_t hole_len; ++ + isBeyondEOF = true; + if (count) { + if (c) +diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c +index 532cda99644ee..036ebd892b852 100644 +--- a/fs/udf/truncate.c ++++ b/fs/udf/truncate.c +@@ -120,60 +120,42 @@ void udf_truncate_tail_extent(struct inode *inode) + + void udf_discard_prealloc(struct inode *inode) + { +- struct extent_position epos = { NULL, 0, {0, 0} }; ++ struct extent_position epos = {}; ++ struct extent_position prev_epos = {}; + struct kernel_lb_addr eloc; + uint32_t elen; + uint64_t lbcount = 0; + int8_t etype = -1, netype; +- int adsize; + struct udf_inode_info *iinfo = UDF_I(inode); ++ int bsize = 1 << inode->i_blkbits; + + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB || +- inode->i_size == iinfo->i_lenExtents) ++ ALIGN(inode->i_size, bsize) == ALIGN(iinfo->i_lenExtents, bsize)) + return; + +- if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) +- adsize = sizeof(struct short_ad); +- else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) +- adsize = sizeof(struct long_ad); +- else +- adsize = 0; +- + epos.block = iinfo->i_location; + + /* Find the last extent in the file */ +- while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { +- etype = netype; ++ while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 0)) != -1) { ++ brelse(prev_epos.bh); ++ prev_epos = epos; ++ if (prev_epos.bh) ++ get_bh(prev_epos.bh); ++ ++ etype = udf_next_aext(inode, &epos, &eloc, &elen, 1); + lbcount += elen; + } + if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { +- epos.offset -= adsize; + lbcount -= elen; +- extent_trunc(inode, &epos, &eloc, etype, elen, 0); +- if (!epos.bh) { +- iinfo->i_lenAlloc = +- epos.offset - +- udf_file_entry_alloc_offset(inode); +- mark_inode_dirty(inode); +- } else { +- struct allocExtDesc *aed = +- (struct allocExtDesc *)(epos.bh->b_data); +- aed->lengthAllocDescs = +- cpu_to_le32(epos.offset - +- sizeof(struct allocExtDesc)); +- if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || +- UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) +- udf_update_tag(epos.bh->b_data, epos.offset); +- else +- udf_update_tag(epos.bh->b_data, +- sizeof(struct allocExtDesc)); +- mark_buffer_dirty_inode(epos.bh, inode); +- } ++ udf_delete_aext(inode, prev_epos); ++ udf_free_blocks(inode->i_sb, inode, &eloc, 0, ++ DIV_ROUND_UP(elen, 1 << inode->i_blkbits)); + } + /* This inode entry is in-memory only and thus we don't have to mark + * the inode dirty */ + iinfo->i_lenExtents = lbcount; + brelse(epos.bh); ++ brelse(prev_epos.bh); + } + + static void udf_update_alloc_ext_desc(struct inode *inode, +diff --git a/include/linux/module.h b/include/linux/module.h +index 518296ea7f73a..e72db35fbf759 100644 +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -879,8 +879,17 @@ static inline bool module_sig_ok(struct module *module) + } + #endif /* CONFIG_MODULE_SIG */ + ++#if defined(CONFIG_MODULES) && defined(CONFIG_KALLSYMS) + int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, + struct module *, unsigned long), + void *data); ++#else ++static inline int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, ++ struct module *, unsigned long), ++ void *data) ++{ ++ return -EOPNOTSUPP; ++} ++#endif /* CONFIG_MODULES && CONFIG_KALLSYMS */ + + #endif /* _LINUX_MODULE_H */ +diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c +index f5c5c9175333d..4523f99b03589 100644 +--- a/kernel/module/kallsyms.c ++++ b/kernel/module/kallsyms.c +@@ -494,7 +494,6 @@ unsigned long module_kallsyms_lookup_name(const char *name) + return ret; + } + +-#ifdef CONFIG_LIVEPATCH + int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, + struct module *, unsigned long), + void *data) +@@ -531,4 +530,3 @@ out: + mutex_unlock(&module_mutex); + return ret; + } +-#endif /* CONFIG_LIVEPATCH */ +diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c +index ec4b81007796c..da8e7b6951793 100644 +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -2264,6 +2264,8 @@ struct bpf_kprobe_multi_link { + unsigned long *addrs; + u64 *cookies; + u32 cnt; ++ u32 mods_cnt; ++ struct module **mods; + }; + + struct bpf_kprobe_multi_run_ctx { +@@ -2319,6 +2321,14 @@ error: + return err; + } + ++static void kprobe_multi_put_modules(struct module **mods, u32 cnt) ++{ ++ u32 i; ++ ++ for (i = 0; i < cnt; i++) ++ module_put(mods[i]); ++} ++ + static void free_user_syms(struct user_syms *us) + { + kvfree(us->syms); +@@ -2331,6 +2341,7 @@ static void bpf_kprobe_multi_link_release(struct bpf_link *link) + + kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link); + unregister_fprobe(&kmulti_link->fp); ++ kprobe_multi_put_modules(kmulti_link->mods, kmulti_link->mods_cnt); + } + + static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link) +@@ -2340,6 +2351,7 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link) + kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link); + kvfree(kmulti_link->addrs); + kvfree(kmulti_link->cookies); ++ kfree(kmulti_link->mods); + kfree(kmulti_link); + } + +@@ -2362,7 +2374,7 @@ static void bpf_kprobe_multi_cookie_swap(void *a, void *b, int size, const void + swap(*cookie_a, *cookie_b); + } + +-static int __bpf_kprobe_multi_cookie_cmp(const void *a, const void *b) ++static int bpf_kprobe_multi_addrs_cmp(const void *a, const void *b) + { + const unsigned long *addr_a = a, *addr_b = b; + +@@ -2373,7 +2385,7 @@ static int __bpf_kprobe_multi_cookie_cmp(const void *a, const void *b) + + static int bpf_kprobe_multi_cookie_cmp(const void *a, const void *b, const void *priv) + { +- return __bpf_kprobe_multi_cookie_cmp(a, b); ++ return bpf_kprobe_multi_addrs_cmp(a, b); + } + + static u64 bpf_kprobe_multi_cookie(struct bpf_run_ctx *ctx) +@@ -2391,7 +2403,7 @@ static u64 bpf_kprobe_multi_cookie(struct bpf_run_ctx *ctx) + return 0; + entry_ip = run_ctx->entry_ip; + addr = bsearch(&entry_ip, link->addrs, link->cnt, sizeof(entry_ip), +- __bpf_kprobe_multi_cookie_cmp); ++ bpf_kprobe_multi_addrs_cmp); + if (!addr) + return 0; + cookie = link->cookies + (addr - link->addrs); +@@ -2475,6 +2487,71 @@ static void symbols_swap_r(void *a, void *b, int size, const void *priv) + } + } + ++struct module_addr_args { ++ unsigned long *addrs; ++ u32 addrs_cnt; ++ struct module **mods; ++ int mods_cnt; ++ int mods_cap; ++}; ++ ++static int module_callback(void *data, const char *name, ++ struct module *mod, unsigned long addr) ++{ ++ struct module_addr_args *args = data; ++ struct module **mods; ++ ++ /* We iterate all modules symbols and for each we: ++ * - search for it in provided addresses array ++ * - if found we check if we already have the module pointer stored ++ * (we iterate modules sequentially, so we can check just the last ++ * module pointer) ++ * - take module reference and store it ++ */ ++ if (!bsearch(&addr, args->addrs, args->addrs_cnt, sizeof(addr), ++ bpf_kprobe_multi_addrs_cmp)) ++ return 0; ++ ++ if (args->mods && args->mods[args->mods_cnt - 1] == mod) ++ return 0; ++ ++ if (args->mods_cnt == args->mods_cap) { ++ args->mods_cap = max(16, args->mods_cap * 3 / 2); ++ mods = krealloc_array(args->mods, args->mods_cap, sizeof(*mods), GFP_KERNEL); ++ if (!mods) ++ return -ENOMEM; ++ args->mods = mods; ++ } ++ ++ if (!try_module_get(mod)) ++ return -EINVAL; ++ ++ args->mods[args->mods_cnt] = mod; ++ args->mods_cnt++; ++ return 0; ++} ++ ++static int get_modules_for_addrs(struct module ***mods, unsigned long *addrs, u32 addrs_cnt) ++{ ++ struct module_addr_args args = { ++ .addrs = addrs, ++ .addrs_cnt = addrs_cnt, ++ }; ++ int err; ++ ++ /* We return either err < 0 in case of error, ... */ ++ err = module_kallsyms_on_each_symbol(module_callback, &args); ++ if (err) { ++ kprobe_multi_put_modules(args.mods, args.mods_cnt); ++ kfree(args.mods); ++ return err; ++ } ++ ++ /* or number of modules found if everything is ok. */ ++ *mods = args.mods; ++ return args.mods_cnt; ++} ++ + int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) + { + struct bpf_kprobe_multi_link *link = NULL; +@@ -2585,10 +2662,25 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr + bpf_kprobe_multi_cookie_cmp, + bpf_kprobe_multi_cookie_swap, + link); ++ } else { ++ /* ++ * We need to sort addrs array even if there are no cookies ++ * provided, to allow bsearch in get_modules_for_addrs. ++ */ ++ sort(addrs, cnt, sizeof(*addrs), ++ bpf_kprobe_multi_addrs_cmp, NULL); ++ } ++ ++ err = get_modules_for_addrs(&link->mods, addrs, cnt); ++ if (err < 0) { ++ bpf_link_cleanup(&link_primer); ++ return err; + } ++ link->mods_cnt = err; + + err = register_fprobe_ips(&link->fp, addrs, cnt); + if (err) { ++ kprobe_multi_put_modules(link->mods, link->mods_cnt); + bpf_link_cleanup(&link_primer); + return err; + } +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index 9e6231f4a04f7..768306ec3c941 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -8261,6 +8261,10 @@ struct kallsyms_data { + size_t found; + }; + ++/* This function gets called for all kernel and module symbols ++ * and returns 1 in case we resolved all the requested symbols, ++ * 0 otherwise. ++ */ + static int kallsyms_callback(void *data, const char *name, + struct module *mod, unsigned long addr) + { +@@ -8304,17 +8308,19 @@ static int kallsyms_callback(void *data, const char *name, + int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *addrs) + { + struct kallsyms_data args; +- int err; ++ int found_all; + + memset(addrs, 0, sizeof(*addrs) * cnt); + args.addrs = addrs; + args.syms = sorted_syms; + args.cnt = cnt; + args.found = 0; +- err = kallsyms_on_each_symbol(kallsyms_callback, &args); +- if (err < 0) +- return err; +- return args.found == args.cnt ? 0 : -ESRCH; ++ ++ found_all = kallsyms_on_each_symbol(kallsyms_callback, &args); ++ if (found_all) ++ return 0; ++ found_all = module_kallsyms_on_each_symbol(kallsyms_callback, &args); ++ return found_all ? 0 : -ESRCH; + } + + #ifdef CONFIG_SYSCTL +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 9c24947aa41ef..9fdede5fe71c7 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -4453,7 +4453,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + + chan->ident = cmd->ident; + l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); +- chan->num_conf_rsp++; ++ if (chan->num_conf_rsp < L2CAP_CONF_MAX_CONF_RSP) ++ chan->num_conf_rsp++; + + /* Reset config buffer. */ + chan->conf_len = 0; +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index e05cfc2e49aeb..1e313982af02a 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -627,7 +627,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, + pr_err("encrypted key: instantiation of keys using provided decrypted data is disabled since CONFIG_USER_DECRYPTED_DATA is set to false\n"); + return ERR_PTR(-EINVAL); + } +- if (strlen(decrypted_data) != decrypted_datalen) { ++ if (strlen(decrypted_data) != decrypted_datalen * 2) { + pr_err("encrypted key: decrypted data provided does not match decrypted data length provided\n"); + return ERR_PTR(-EINVAL); + } +@@ -791,8 +791,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, + ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv); + } else if (decrypted_data) { + get_random_bytes(epayload->iv, ivsize); +- memcpy(epayload->decrypted_data, decrypted_data, +- epayload->decrypted_datalen); ++ ret = hex2bin(epayload->decrypted_data, decrypted_data, ++ epayload->decrypted_datalen); + } else { + get_random_bytes(epayload->iv, ivsize); + get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen); +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index d8c6af9e43ad6..ce6ea8819562b 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -9376,6 +9376,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), ++ SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), + SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), +diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +index 792cb15bac40f..ac5d7c1396fb4 100644 +--- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c ++++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +@@ -88,6 +88,23 @@ __weak noinline struct file *bpf_testmod_return_ptr(int arg) + } + } + ++noinline int bpf_testmod_fentry_test1(int a) ++{ ++ return a + 1; ++} ++ ++noinline int bpf_testmod_fentry_test2(int a, u64 b) ++{ ++ return a + b; ++} ++ ++noinline int bpf_testmod_fentry_test3(char a, int b, u64 c) ++{ ++ return a + b + c; ++} ++ ++int bpf_testmod_fentry_ok; ++ + noinline ssize_t + bpf_testmod_test_read(struct file *file, struct kobject *kobj, + struct bin_attribute *bin_attr, +@@ -119,6 +136,13 @@ bpf_testmod_test_read(struct file *file, struct kobject *kobj, + return snprintf(buf, len, "%d\n", writable.val); + } + ++ if (bpf_testmod_fentry_test1(1) != 2 || ++ bpf_testmod_fentry_test2(2, 3) != 5 || ++ bpf_testmod_fentry_test3(4, 5, 6) != 15) ++ goto out; ++ ++ bpf_testmod_fentry_ok = 1; ++out: + return -EIO; /* always fail */ + } + EXPORT_SYMBOL(bpf_testmod_test_read); +diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_testmod_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_testmod_test.c +new file mode 100644 +index 0000000000000..1fbe7e4ac00ab +--- /dev/null ++++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_testmod_test.c +@@ -0,0 +1,89 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include <test_progs.h> ++#include "kprobe_multi.skel.h" ++#include "trace_helpers.h" ++#include "bpf/libbpf_internal.h" ++ ++static void kprobe_multi_testmod_check(struct kprobe_multi *skel) ++{ ++ ASSERT_EQ(skel->bss->kprobe_testmod_test1_result, 1, "kprobe_test1_result"); ++ ASSERT_EQ(skel->bss->kprobe_testmod_test2_result, 1, "kprobe_test2_result"); ++ ASSERT_EQ(skel->bss->kprobe_testmod_test3_result, 1, "kprobe_test3_result"); ++ ++ ASSERT_EQ(skel->bss->kretprobe_testmod_test1_result, 1, "kretprobe_test1_result"); ++ ASSERT_EQ(skel->bss->kretprobe_testmod_test2_result, 1, "kretprobe_test2_result"); ++ ASSERT_EQ(skel->bss->kretprobe_testmod_test3_result, 1, "kretprobe_test3_result"); ++} ++ ++static void test_testmod_attach_api(struct bpf_kprobe_multi_opts *opts) ++{ ++ struct kprobe_multi *skel = NULL; ++ ++ skel = kprobe_multi__open_and_load(); ++ if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) ++ return; ++ ++ skel->bss->pid = getpid(); ++ ++ skel->links.test_kprobe_testmod = bpf_program__attach_kprobe_multi_opts( ++ skel->progs.test_kprobe_testmod, ++ NULL, opts); ++ if (!skel->links.test_kprobe_testmod) ++ goto cleanup; ++ ++ opts->retprobe = true; ++ skel->links.test_kretprobe_testmod = bpf_program__attach_kprobe_multi_opts( ++ skel->progs.test_kretprobe_testmod, ++ NULL, opts); ++ if (!skel->links.test_kretprobe_testmod) ++ goto cleanup; ++ ++ ASSERT_OK(trigger_module_test_read(1), "trigger_read"); ++ kprobe_multi_testmod_check(skel); ++ ++cleanup: ++ kprobe_multi__destroy(skel); ++} ++ ++static void test_testmod_attach_api_addrs(void) ++{ ++ LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); ++ unsigned long long addrs[3]; ++ ++ addrs[0] = ksym_get_addr("bpf_testmod_fentry_test1"); ++ ASSERT_NEQ(addrs[0], 0, "ksym_get_addr"); ++ addrs[1] = ksym_get_addr("bpf_testmod_fentry_test2"); ++ ASSERT_NEQ(addrs[1], 0, "ksym_get_addr"); ++ addrs[2] = ksym_get_addr("bpf_testmod_fentry_test3"); ++ ASSERT_NEQ(addrs[2], 0, "ksym_get_addr"); ++ ++ opts.addrs = (const unsigned long *) addrs; ++ opts.cnt = ARRAY_SIZE(addrs); ++ ++ test_testmod_attach_api(&opts); ++} ++ ++static void test_testmod_attach_api_syms(void) ++{ ++ LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); ++ const char *syms[3] = { ++ "bpf_testmod_fentry_test1", ++ "bpf_testmod_fentry_test2", ++ "bpf_testmod_fentry_test3", ++ }; ++ ++ opts.syms = syms; ++ opts.cnt = ARRAY_SIZE(syms); ++ test_testmod_attach_api(&opts); ++} ++ ++void serial_test_kprobe_multi_testmod_test(void) ++{ ++ if (!ASSERT_OK(load_kallsyms_refresh(), "load_kallsyms_refresh")) ++ return; ++ ++ if (test__start_subtest("testmod_attach_api_syms")) ++ test_testmod_attach_api_syms(); ++ if (test__start_subtest("testmod_attach_api_addrs")) ++ test_testmod_attach_api_addrs(); ++} +diff --git a/tools/testing/selftests/bpf/prog_tests/module_attach.c b/tools/testing/selftests/bpf/prog_tests/module_attach.c +index 6d0e50dcf47cc..7fc01ff490db7 100644 +--- a/tools/testing/selftests/bpf/prog_tests/module_attach.c ++++ b/tools/testing/selftests/bpf/prog_tests/module_attach.c +@@ -103,6 +103,13 @@ void test_module_attach(void) + ASSERT_ERR(delete_module("bpf_testmod", 0), "delete_module"); + bpf_link__destroy(link); + ++ link = bpf_program__attach(skel->progs.kprobe_multi); ++ if (!ASSERT_OK_PTR(link, "attach_kprobe_multi")) ++ goto cleanup; ++ ++ ASSERT_ERR(delete_module("bpf_testmod", 0), "delete_module"); ++ bpf_link__destroy(link); ++ + cleanup: + test_module_attach__destroy(skel); + } +diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi.c b/tools/testing/selftests/bpf/progs/kprobe_multi.c +index 98c3399e15c03..9e1ca8e34913c 100644 +--- a/tools/testing/selftests/bpf/progs/kprobe_multi.c ++++ b/tools/testing/selftests/bpf/progs/kprobe_multi.c +@@ -110,3 +110,53 @@ int test_kretprobe_manual(struct pt_regs *ctx) + kprobe_multi_check(ctx, true); + return 0; + } ++ ++extern const void bpf_testmod_fentry_test1 __ksym; ++extern const void bpf_testmod_fentry_test2 __ksym; ++extern const void bpf_testmod_fentry_test3 __ksym; ++ ++__u64 kprobe_testmod_test1_result = 0; ++__u64 kprobe_testmod_test2_result = 0; ++__u64 kprobe_testmod_test3_result = 0; ++ ++__u64 kretprobe_testmod_test1_result = 0; ++__u64 kretprobe_testmod_test2_result = 0; ++__u64 kretprobe_testmod_test3_result = 0; ++ ++static void kprobe_multi_testmod_check(void *ctx, bool is_return) ++{ ++ if (bpf_get_current_pid_tgid() >> 32 != pid) ++ return; ++ ++ __u64 addr = bpf_get_func_ip(ctx); ++ ++ if (is_return) { ++ if ((const void *) addr == &bpf_testmod_fentry_test1) ++ kretprobe_testmod_test1_result = 1; ++ if ((const void *) addr == &bpf_testmod_fentry_test2) ++ kretprobe_testmod_test2_result = 1; ++ if ((const void *) addr == &bpf_testmod_fentry_test3) ++ kretprobe_testmod_test3_result = 1; ++ } else { ++ if ((const void *) addr == &bpf_testmod_fentry_test1) ++ kprobe_testmod_test1_result = 1; ++ if ((const void *) addr == &bpf_testmod_fentry_test2) ++ kprobe_testmod_test2_result = 1; ++ if ((const void *) addr == &bpf_testmod_fentry_test3) ++ kprobe_testmod_test3_result = 1; ++ } ++} ++ ++SEC("kprobe.multi") ++int test_kprobe_testmod(struct pt_regs *ctx) ++{ ++ kprobe_multi_testmod_check(ctx, false); ++ return 0; ++} ++ ++SEC("kretprobe.multi") ++int test_kretprobe_testmod(struct pt_regs *ctx) ++{ ++ kprobe_multi_testmod_check(ctx, true); ++ return 0; ++} +diff --git a/tools/testing/selftests/bpf/progs/test_module_attach.c b/tools/testing/selftests/bpf/progs/test_module_attach.c +index 08628afedb779..8a1b50f3a002d 100644 +--- a/tools/testing/selftests/bpf/progs/test_module_attach.c ++++ b/tools/testing/selftests/bpf/progs/test_module_attach.c +@@ -110,4 +110,10 @@ int BPF_PROG(handle_fmod_ret, + return 0; /* don't override the exit code */ + } + ++SEC("kprobe.multi/bpf_testmod_test_read") ++int BPF_PROG(kprobe_multi) ++{ ++ return 0; ++} ++ + char _license[] SEC("license") = "GPL"; +diff --git a/tools/testing/selftests/bpf/trace_helpers.c b/tools/testing/selftests/bpf/trace_helpers.c +index 9c4be2cdb21a0..09a16a77bae4b 100644 +--- a/tools/testing/selftests/bpf/trace_helpers.c ++++ b/tools/testing/selftests/bpf/trace_helpers.c +@@ -23,7 +23,7 @@ static int ksym_cmp(const void *p1, const void *p2) + return ((struct ksym *)p1)->addr - ((struct ksym *)p2)->addr; + } + +-int load_kallsyms(void) ++int load_kallsyms_refresh(void) + { + FILE *f; + char func[256], buf[256]; +@@ -31,12 +31,7 @@ int load_kallsyms(void) + void *addr; + int i = 0; + +- /* +- * This is called/used from multiplace places, +- * load symbols just once. +- */ +- if (sym_cnt) +- return 0; ++ sym_cnt = 0; + + f = fopen("/proc/kallsyms", "r"); + if (!f) +@@ -57,6 +52,17 @@ int load_kallsyms(void) + return 0; + } + ++int load_kallsyms(void) ++{ ++ /* ++ * This is called/used from multiplace places, ++ * load symbols just once. ++ */ ++ if (sym_cnt) ++ return 0; ++ return load_kallsyms_refresh(); ++} ++ + struct ksym *ksym_search(long key) + { + int start = 0, end = sym_cnt; +diff --git a/tools/testing/selftests/bpf/trace_helpers.h b/tools/testing/selftests/bpf/trace_helpers.h +index 238a9c98cde27..53efde0e2998e 100644 +--- a/tools/testing/selftests/bpf/trace_helpers.h ++++ b/tools/testing/selftests/bpf/trace_helpers.h +@@ -10,6 +10,8 @@ struct ksym { + }; + + int load_kallsyms(void); ++int load_kallsyms_refresh(void); ++ + struct ksym *ksym_search(long key); + long ksym_get_addr(const char *name); + +diff --git a/tools/testing/selftests/net/toeplitz.sh b/tools/testing/selftests/net/toeplitz.sh +index 0a49907cd4fef..da5bfd834effe 100755 +--- a/tools/testing/selftests/net/toeplitz.sh ++++ b/tools/testing/selftests/net/toeplitz.sh +@@ -32,7 +32,7 @@ DEV="eth0" + # This is determined by reading the RSS indirection table using ethtool. + get_rss_cfg_num_rxqs() { + echo $(ethtool -x "${DEV}" | +- egrep [[:space:]]+[0-9]+:[[:space:]]+ | ++ grep -E [[:space:]]+[0-9]+:[[:space:]]+ | + cut -d: -f2- | + awk '{$1=$1};1' | + tr ' ' '\n' |
