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' |


Reply via email to