From: Greg Kroah-Hartman Date: Mon, 19 Dec 2022 12:30:26 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v5.10.161~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aa3ef92e922c8e91f42acc02ac9b6fa2c962abe3;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: udf-discard-preallocation-before-extending-file-with-a-hole.patch udf-do-not-bother-looking-for-prealloc-extents-if-i_lenextents-matches-i_size.patch udf-fix-extending-file-within-last-block.patch udf-fix-preallocation-discarding-at-indirect-extent-boundary.patch usb-gadget-uvc-prevent-buffer-overflow-in-setup-handler.patch usb-serial-cp210x-add-kamstrup-rf-sniffer-pids.patch --- diff --git a/queue-4.9/series b/queue-4.9/series index f4cc9aff1d4..75cc726ad38 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -4,3 +4,9 @@ block-unhash-blkdev-part-inode-when-the-part-is-deleted.patch asoc-ops-check-bounds-for-second-channel-in-snd_soc_.patch can-sja1000-fix-size-of-ocr_mode_mask-define.patch asoc-ops-correct-bounds-check-for-second-channel-on-sx-controls.patch +udf-discard-preallocation-before-extending-file-with-a-hole.patch +udf-fix-preallocation-discarding-at-indirect-extent-boundary.patch +udf-do-not-bother-looking-for-prealloc-extents-if-i_lenextents-matches-i_size.patch +udf-fix-extending-file-within-last-block.patch +usb-gadget-uvc-prevent-buffer-overflow-in-setup-handler.patch +usb-serial-cp210x-add-kamstrup-rf-sniffer-pids.patch diff --git a/queue-4.9/udf-discard-preallocation-before-extending-file-with-a-hole.patch b/queue-4.9/udf-discard-preallocation-before-extending-file-with-a-hole.patch new file mode 100644 index 00000000000..cfab451cf4b --- /dev/null +++ b/queue-4.9/udf-discard-preallocation-before-extending-file-with-a-hole.patch @@ -0,0 +1,131 @@ +From 16d0556568148bdcaa45d077cac9f8f7077cf70a Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 7 Dec 2022 18:17:34 +0100 +Subject: udf: Discard preallocation before extending file with a hole + +From: Jan Kara + +commit 16d0556568148bdcaa45d077cac9f8f7077cf70a upstream. + +When extending file with a hole, we tried to preserve existing +preallocation for the file. However that is not very useful and +complicates code because the previous extent may need to be rounded to +block boundary as well (which we forgot to do thus causing data +corruption for sequence like: + +xfs_io -f -c "pwrite 0x75e63 11008" -c "truncate 0x7b24b" \ + -c "truncate 0xabaa3" -c "pwrite 0xac70b 22954" \ + -c "pwrite 0x93a43 11358" -c "pwrite 0xb8e65 52211" file + +with 512-byte block size. Just discard preallocation before extending +file to simplify things and also fix this data corruption. + +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/inode.c | 46 ++++++++++++++++++---------------------------- + 1 file changed, 18 insertions(+), 28 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -442,6 +442,12 @@ static int udf_get_block(struct inode *i + 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) +@@ -491,8 +497,6 @@ static int udf_do_extend_file(struct ino + 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 = {}; +- int prealloc_len = 0; + struct udf_inode_info *iinfo; + int err; + +@@ -513,19 +517,6 @@ static int udf_do_extend_file(struct ino + ~(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) { +@@ -553,7 +544,7 @@ static int udf_do_extend_file(struct ino + * 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); + } + +@@ -587,17 +578,6 @@ static int udf_do_extend_file(struct ino + } + + 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); +@@ -650,8 +630,17 @@ static int udf_extend_file(struct inode + 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); ++ /* We don't expect extents past EOF... */ ++ WARN_ON_ONCE(etype != -1 && ++ 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))) { +@@ -783,10 +772,11 @@ static sector_t inode_getblk(struct inod + return newblock; + } + +- /* 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/queue-4.9/udf-do-not-bother-looking-for-prealloc-extents-if-i_lenextents-matches-i_size.patch b/queue-4.9/udf-do-not-bother-looking-for-prealloc-extents-if-i_lenextents-matches-i_size.patch new file mode 100644 index 00000000000..552b7bf733f --- /dev/null +++ b/queue-4.9/udf-do-not-bother-looking-for-prealloc-extents-if-i_lenextents-matches-i_size.patch @@ -0,0 +1,34 @@ +From 6ad53f0f71c52871202a7bf096feb2c59db33fc5 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 7 Dec 2022 17:34:33 +0100 +Subject: udf: Do not bother looking for prealloc extents if i_lenExtents matches i_size + +From: Jan Kara + +commit 6ad53f0f71c52871202a7bf096feb2c59db33fc5 upstream. + +If rounded block-rounded i_lenExtents matches block rounded i_size, +there are no preallocation extents. Do not bother walking extent linked +list. + +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/truncate.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/udf/truncate.c ++++ b/fs/udf/truncate.c +@@ -127,9 +127,10 @@ void udf_discard_prealloc(struct inode * + uint64_t lbcount = 0; + int8_t etype = -1, netype; + 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; + + epos.block = iinfo->i_location; diff --git a/queue-4.9/udf-fix-extending-file-within-last-block.patch b/queue-4.9/udf-fix-extending-file-within-last-block.patch new file mode 100644 index 00000000000..349c6f75dbd --- /dev/null +++ b/queue-4.9/udf-fix-extending-file-within-last-block.patch @@ -0,0 +1,99 @@ +From 1f3868f06855c97a4954c99b36f3fc9eb8f60326 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 8 Dec 2022 13:03:30 +0100 +Subject: udf: Fix extending file within last block + +From: Jan Kara + +commit 1f3868f06855c97a4954c99b36f3fc9eb8f60326 upstream. + +When extending file within last block it can happen that the extent is +already rounded to the blocksize and thus contains the offset we want to +grow up to. In such case we would mistakenly expand the last extent and +make it one block longer than it should be, exposing unallocated block +in a file and causing data corruption. Fix the problem by properly +detecting this case and bailing out. + +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/inode.c | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -593,13 +593,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; + +@@ -616,12 +620,12 @@ static int udf_extend_file(struct inode + 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); +@@ -637,9 +641,9 @@ static int udf_extend_file(struct inode + 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(etype != -1 && ++ 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)) || +@@ -656,19 +660,17 @@ static int udf_extend_file(struct inode + 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) diff --git a/queue-4.9/udf-fix-preallocation-discarding-at-indirect-extent-boundary.patch b/queue-4.9/udf-fix-preallocation-discarding-at-indirect-extent-boundary.patch new file mode 100644 index 00000000000..d87d45cb622 --- /dev/null +++ b/queue-4.9/udf-fix-preallocation-discarding-at-indirect-extent-boundary.patch @@ -0,0 +1,96 @@ +From cfe4c1b25dd6d2f056afc00b7c98bcb3dd0b1fc3 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 7 Dec 2022 17:25:10 +0100 +Subject: udf: Fix preallocation discarding at indirect extent boundary + +From: Jan Kara + +commit cfe4c1b25dd6d2f056afc00b7c98bcb3dd0b1fc3 upstream. + +When preallocation extent is the first one in the extent block, the +code would corrupt extent tree header instead. Fix the problem and use +udf_delete_aext() for deleting extent to avoid some code duplication. + +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/truncate.c | 45 +++++++++++++-------------------------------- + 1 file changed, 13 insertions(+), 32 deletions(-) + +--- a/fs/udf/truncate.c ++++ b/fs/udf/truncate.c +@@ -120,60 +120,41 @@ void udf_truncate_tail_extent(struct ino + + 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); + + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB || + inode->i_size == iinfo->i_lenExtents) + 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/queue-4.9/usb-gadget-uvc-prevent-buffer-overflow-in-setup-handler.patch b/queue-4.9/usb-gadget-uvc-prevent-buffer-overflow-in-setup-handler.patch new file mode 100644 index 00000000000..247bc40f543 --- /dev/null +++ b/queue-4.9/usb-gadget-uvc-prevent-buffer-overflow-in-setup-handler.patch @@ -0,0 +1,40 @@ +From 4c92670b16727365699fe4b19ed32013bab2c107 Mon Sep 17 00:00:00 2001 +From: Szymon Heidrich +Date: Tue, 6 Dec 2022 15:13:01 +0100 +Subject: usb: gadget: uvc: Prevent buffer overflow in setup handler + +From: Szymon Heidrich + +commit 4c92670b16727365699fe4b19ed32013bab2c107 upstream. + +Setup function uvc_function_setup permits control transfer +requests with up to 64 bytes of payload (UVC_MAX_REQUEST_SIZE), +data stage handler for OUT transfer uses memcpy to copy req->actual +bytes to uvc_event->data.data array of size 60. This may result +in an overflow of 4 bytes. + +Fixes: cdda479f15cd ("USB gadget: video class function driver") +Cc: stable +Reviewed-by: Laurent Pinchart +Reviewed-by: Daniel Scally +Signed-off-by: Szymon Heidrich +Link: https://lore.kernel.org/r/20221206141301.51305-1-szymon.heidrich@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_uvc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/usb/gadget/function/f_uvc.c ++++ b/drivers/usb/gadget/function/f_uvc.c +@@ -220,8 +220,9 @@ uvc_function_ep0_complete(struct usb_ep + + 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/queue-4.9/usb-serial-cp210x-add-kamstrup-rf-sniffer-pids.patch b/queue-4.9/usb-serial-cp210x-add-kamstrup-rf-sniffer-pids.patch new file mode 100644 index 00000000000..e910b78a00e --- /dev/null +++ b/queue-4.9/usb-serial-cp210x-add-kamstrup-rf-sniffer-pids.patch @@ -0,0 +1,37 @@ +From e88906b169ebcb8046e8f0ad76edd09ab41cfdfe Mon Sep 17 00:00:00 2001 +From: Bruno Thomsen +Date: Sun, 27 Nov 2022 18:08:11 +0100 +Subject: USB: serial: cp210x: add Kamstrup RF sniffer PIDs + +From: Bruno Thomsen + +commit e88906b169ebcb8046e8f0ad76edd09ab41cfdfe upstream. + +The RF sniffers are based on cp210x where the RF frontends +are based on a different USB stack. + +RF sniffers can analyze packets meta data including power level +and perform packet injection. + +Can be used to perform RF frontend self-test when connected to +a concentrator, ex. arch/arm/boot/dts/imx7d-flex-concentrator.dts + +Signed-off-by: Bruno Thomsen +Cc: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/cp210x.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -193,6 +193,8 @@ static const struct usb_device_id id_tab + { 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 */