6.1.107-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 125/321 drm/amdkfd: Move dma unmapping after TLB flush
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philip Yang <[email protected]>
[ Upstream commit 101b8104307eac734f2dfa4d3511430b0b631c73 ]
Otherwise GPU may access the stale mapping and generate IOMMU IO_PAGE_FAULT.
Move this to inside p->mutex to prevent multiple threads mapping and unmapping concurrently race condition.
After kfd_mem_dmaunmap_attachment is removed from unmap_bo_from_gpuvm, kfd_mem_dmaunmap_attachment is called if failed to map to GPUs, and before free the mem attachment in case failed to unmap from GPUs.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 + .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 26 ++++++++++++++++--- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 20 ++++++++------ 3 files changed, 35 insertions(+), 12 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +1 -0
@@ -286,6 +286,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv);int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu (struct amdgpu_device *adev,struct kgd_mem *mem,void *drm_priv); +void amdgpu_amdkfd_gpuvm_dmaunmap_mem (struct kgd_mem *mem,void *drm_priv);int amdgpu_amdkfd_gpuvm_sync_memory (struct amdgpu_device *adev,struct kgd_mem *mem,bool intr); int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +22 -4
@@ -719,7 +719,7 @@ kfd_mem_dmaunmap_sg_bo(struct kgd_mem *mem,enum dma_data_direction dir;if (unlikely (!ttm->sg)) { -pr_err ("SG Table of BO is UNEXPECTEDLY NULL" ); +pr_debug ("SG Table of BO is NULL" );return ; }
@@ -1226,8 +1226,6 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem,amdgpu_vm_clear_freed (adev, vm, &bo_va->last_pt_update);amdgpu_sync_fence (sync, bo_va->last_pt_update); - -kfd_mem_dmaunmap_attachment (mem, entry); } static int update_gpuvm_pte(struct kgd_mem *mem,
@@ -1282,6 +1280,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem, update_gpuvm_pte_failed:unmap_bo_from_gpuvm (mem, entry, sync); +kfd_mem_dmaunmap_attachment (mem, entry);return ret; }
@@ -1852,8 +1851,10 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( mem->va + bo_size * (1 + mem->aql_queue));/* Remove from VM internal data structures */ -list_for_each_entry_safe (entry, tmp, &mem->attachments, list) +list_for_each_entry_safe (entry, tmp, &mem->attachments, list) { +kfd_mem_dmaunmap_attachment (mem, entry);kfd_mem_detach (entry); + } ret =unreserve_bo_and_vms (&ctx, false, false);
@@ -2024,6 +2025,23 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(return ret; } +void amdgpu_amdkfd_gpuvm_dmaunmap_mem (struct kgd_mem *mem,void *drm_priv) +{ +struct kfd_mem_attachment *entry; +struct amdgpu_vm *vm; + + vm =drm_priv_to_vm (drm_priv); + +mutex_lock (&mem->lock); + +list_for_each_entry (entry, &mem->attachments, list) { +if (entry->bo_va->base.vm == vm) +kfd_mem_dmaunmap_attachment (mem, entry); + } + +mutex_unlock (&mem->lock); +} +int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu (struct amdgpu_device *adev,struct kgd_mem *mem,void *drm_priv) {
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +12 -8
@@ -1400,17 +1400,21 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, goto sync_memory_failed; } } -mutex_unlock (&p->mutex); -if (flush_tlb) { -/* Flush TLBs after waiting for the page table updates to complete */ -for (i =0 ; i < args->n_devices; i++) { - peer_pdd =kfd_process_device_data_by_id (p, devices_arr[i]); -if (WARN_ON_ONCE (!peer_pdd)) -continue ; +/* Flush TLBs after waiting for the page table updates to complete */ +for (i =0 ; i < args->n_devices; i++) { + peer_pdd =kfd_process_device_data_by_id (p, devices_arr[i]); +if (WARN_ON_ONCE (!peer_pdd)) +continue ; +if (flush_tlb)kfd_flush_tlb (peer_pdd,TLB_FLUSH_HEAVYWEIGHT ); - } + +/* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */ +amdgpu_amdkfd_gpuvm_dmaunmap_mem (mem, peer_pdd->drm_priv); } + +mutex_unlock (&p->mutex); +kfree (devices_arr);return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 126/321 media: radio-isa: use dev_name to fill in bus_info
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil <[email protected]>
[ Upstream commit 8b7f3cf4eb9a95940eaabad3226caeaa0d9aa59d ]
This fixes this warning:
drivers/media/radio/radio-isa.c: In function 'radio_isa_querycap':drivers/media/radio/radio-isa.c:39:57: warning: '%s' directive output may be truncated writing up to 35 bytes into a region of size 28 [-Wformat-truncation=]
39 | snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
| ^~drivers/media/radio/radio-isa.c:39:9: note: 'snprintf' output between 5 and 40 bytes into a destination of size 32
39 | snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- drivers/media/radio/radio-isa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/radio/radio-isa.c +1 -1
@@ -36,7 +36,7 @@ static int radio_isa_querycap(struct file *file, void *priv,strscpy (v->driver, isa->drv->driver.driver.name,sizeof (v->driver));strscpy (v->card, isa->drv->card,sizeof (v->card)); -snprintf (v->bus_info,sizeof (v->bus_info),"ISA:%s" , isa->v4l2_dev.name); +snprintf (v->bus_info,sizeof (v->bus_info),"ISA:%s" ,dev_name (isa->v4l2_dev.dev));return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 127/321 staging: iio: resolver: ad2s1210: fix use before initialization
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner <[email protected]>
[ Upstream commit 7fe2d05cee46b1c4d9f1efaeab08cc31a0dfff60 ]
This fixes a use before initialization in ad2s1210_probe(). The ad2s1210_setup_gpios() function uses st->sdev but it was being called before this field was initialized.
--- drivers/staging/iio/resolver/ad2s1210.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/staging/iio/resolver/ad2s1210.c +4 -3
@@ -657,9 +657,6 @@ static int ad2s1210_probe(struct spi_device *spi)if (!indio_dev)return -ENOMEM ; st =iio_priv (indio_dev); - ret =ad2s1210_setup_gpios (st); -if (ret <0 ) -return ret;spi_set_drvdata (spi, indio_dev);
@@ -670,6 +667,10 @@ static int ad2s1210_probe(struct spi_device *spi) st->resolution =12 ; st->fexcit =AD2S1210_DEF_EXCIT ; + ret =ad2s1210_setup_gpios (st); +if (ret <0 ) +return ret; + indio_dev->info = &ad2s1210_info; indio_dev->modes =INDIO_DIRECT_MODE ; indio_dev->channels = ad2s1210_channels;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 128/321 usb: gadget: uvc: cleanup request when not in correct state
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Grzeschik <[email protected]>
[ Upstream commit 52a39f2cf62bb5430ad1f54cd522dbfdab1d71ba ]
The uvc_video_enable function of the uvc-gadget driver is dequeing and immediately deallocs all requests on its disable codepath. This is not save since the dequeue function is async and does not ensure that the requests are left unlinked in the controller driver.
By adding the ep_free_request into the completion path of the requests we ensure that the request will be properly deallocated.
--- drivers/usb/gadget/function/uvc_video.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/gadget/function/uvc_video.c +6 -0
@@ -259,6 +259,12 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)struct uvc_device *uvc = video->uvc;unsigned long flags; +if (uvc->state ==UVC_STATE_CONNECTED ) { +usb_ep_free_request (video->ep, ureq->req); + ureq->req =NULL ; +return ; + } +switch (req->status) {case 0 :break ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 129/321 drm/amd/display: Validate hw_points_num before using it
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Hung <[email protected]>
[ Upstream commit 58c3b3341cea4f75dc8c003b89f8a6dd8ec55e50 ]
[WHAT]hw_points_num is 0 before ogam LUT is programmed; however, function "dwb3_program_ogam_pwl" assumes hw_points_num is always greater than 0, i.e. substracting it by 1 as an array index.
[HOW]
Check hw_points_num is not equal to 0 before using it.
--- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c +3 -0
@@ -243,6 +243,9 @@ static bool dwb3_program_ogam_lut(return false; } +if (params->hw_points_num ==0 ) +return false; +REG_SET (DWB_OGAM_CONTROL ,0 ,DWB_OGAM_MODE ,2 ); current_mode =dwb3_get_ogam_current (dwbc30);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 130/321 staging: ks7010: disable bh on tx_dev_lock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <[email protected]>
[ Upstream commit 058cbee52ccd7be77e373d31a4f14670cfd32018 ]
As &priv->tx_dev.tx_dev_lock is also acquired by xmit callback which could be call from timer under softirq context, use spin_lock_bh() on it to prevent potential deadlock.
hostif_sme_work()
--> hostif_sme_set_pmksa()
--> hostif_mib_set_request()
--> ks_wlan_hw_tx()
--> spin_lock(&priv->tx_dev.tx_dev_lock)
ks_wlan_start_xmit()
--> hostif_data_request()
--> ks_wlan_hw_tx()
--> spin_lock(&priv->tx_dev.tx_dev_lock)
--- drivers/staging/ks7010/ks7010_sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/ks7010/ks7010_sdio.c +2 -2
@@ -395,9 +395,9 @@ int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size, priv->hostt.buff[priv->hostt.qtail] =le16_to_cpu (hdr->event); priv->hostt.qtail = (priv->hostt.qtail +1 ) %SME_EVENT_BUFF_SIZE ; -spin_lock (&priv->tx_dev.tx_dev_lock); +spin_lock_bh (&priv->tx_dev.tx_dev_lock); result =enqueue_txdev (priv, p, size, complete_handler, skb); -spin_unlock (&priv->tx_dev.tx_dev_lock); +spin_unlock_bh (&priv->tx_dev.tx_dev_lock);if (txq_has_space (priv))queue_delayed_work (priv->wq, &priv->rw_dwork,0 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 131/321 media: s5p-mfc: Fix potential deadlock on condlock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <[email protected]>
[ Upstream commit 04d19e65137e3cd4a5004e624c85c762933d115c ]
As &dev->condlock is acquired under irq context along the following call chain from s5p_mfc_irq(), other acquisition of the same lock inside process context or softirq context should disable irq avoid double lock. enc_post_frame_start() seems to be one such function that execute under process context or softirq context.
<deadlock #1>
enc_post_frame_start()
--> clear_work_bit()
--> spin_loc(&dev->condlock)
<interrupt>
--> s5p_mfc_irq()
--> s5p_mfc_handle_frame()
--> clear_work_bit()
--> spin_lock(&dev->condlock)
This flaw was found by an experimental static analysis tool I am developing for irq-related deadlock.
To prevent the potential deadlock, the patch change clear_work_bit() inside enc_post_frame_start() to clear_work_bit_irqsave().
--- drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c +1 -1
@@ -1297,7 +1297,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)if (ctx->state ==MFCINST_FINISHING && ctx->ref_queue_cnt ==0 ) src_ready = false;if (!src_ready || ctx->dst_queue_cnt ==0 ) -clear_work_bit (ctx); +clear_work_bit_irqsave (ctx);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 132/321 md/raid5-cache: use READ_ONCE/WRITE_ONCE for conf->log
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Kuai <[email protected]>
[ Upstream commit 06a4d0d8c642b5ea654e832b74dca12965356da0 ]
'conf->log' is set with 'reconfig_mutex' grabbed, however, readers are not procted, hence protect it with READ_ONCE/WRITE_ONCE to prevent reading abnormal values.
--- drivers/md/raid5-cache.c | 47 +++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 22 deletions(-)
drivers/md/raid5-cache.c +25 -22
@@ -327,8 +327,9 @@ void r5l_wake_reclaim(struct r5l_log *log, sector_t space);void r5c_check_stripe_cache_usage (struct r5conf *conf) {int total_cached; +struct r5l_log *log =READ_ONCE (conf->log); -if (!r5c_is_writeback (conf->log)) +if (!r5c_is_writeback (log))return ; total_cached = atomic_read(&conf->r5c_cached_partial_stripes) +
@@ -344,7 +345,7 @@ void r5c_check_stripe_cache_usage(struct r5conf *conf)*/ if (total_cached > conf->min_nr_stripes *1 /2 ||atomic_read (&conf->empty_inactive_list_nr) >0 ) -r5l_wake_reclaim (conf->log,0 ); +r5l_wake_reclaim (log,0 ); }/*
@@ -353,7 +354,9 @@ void r5c_check_stripe_cache_usage(struct r5conf *conf)*/ void r5c_check_cached_full_stripe (struct r5conf *conf) { -if (!r5c_is_writeback (conf->log)) +struct r5l_log *log =READ_ONCE (conf->log); + +if (!r5c_is_writeback (log))return ;/*
@@ -363,7 +366,7 @@ void r5c_check_cached_full_stripe(struct r5conf *conf)if (atomic_read (&conf->r5c_cached_full_stripes) >=min (R5C_FULL_STRIPE_FLUSH_BATCH (conf), conf->chunk_sectors >>RAID5_STRIPE_SHIFT (conf))) -r5l_wake_reclaim (conf->log,0 ); +r5l_wake_reclaim (log,0 ); }/*
@@ -396,7 +399,7 @@ void r5c_check_cached_full_stripe(struct r5conf *conf)*/ static sector_t r5c_log_required_to_flush_cache (struct r5conf *conf) { -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);if (!r5c_is_writeback (log))return 0 ;
@@ -449,7 +452,7 @@ static inline void r5c_update_log_state(struct r5l_log *log)void r5c_make_stripe_write_out (struct stripe_head *sh) {struct r5conf *conf = sh->raid_conf; -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);BUG_ON (!r5c_is_writeback (log));
@@ -491,7 +494,7 @@ static void r5c_handle_parity_cached(struct stripe_head *sh)*/ static void r5c_finish_cache_stripe (struct stripe_head *sh) { -struct r5l_log *log = sh->raid_conf->log; +struct r5l_log *log =READ_ONCE (sh->raid_conf->log);if (log->r5c_journal_mode ==R5C_JOURNAL_MODE_WRITE_THROUGH ) {BUG_ON (test_bit (STRIPE_R5C_CACHING , &sh->state));
@@ -692,7 +695,7 @@ static void r5c_disable_writeback_async(struct work_struct *work)/* wait superblock change before suspend */ wait_event (mddev->sb_wait, - conf->log ==NULL || + !READ_ONCE (conf->log) || (!test_bit (MD_SB_CHANGE_PENDING , &mddev->sb_flags) && (locked =mddev_trylock (mddev))));if (locked) {
@@ -1151,7 +1154,7 @@ static void r5l_run_no_space_stripes(struct r5l_log *log)static sector_t r5c_calculate_new_cp (struct r5conf *conf) {struct stripe_head *sh; -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);sector_t new_cp;unsigned long flags;
@@ -1159,12 +1162,12 @@ static sector_t r5c_calculate_new_cp(struct r5conf *conf)return log->next_checkpoint;spin_lock_irqsave (&log->stripe_in_journal_lock, flags); -if (list_empty (&conf->log->stripe_in_journal_list)) { +if (list_empty (&log->stripe_in_journal_list)) {/* all stripes flushed */ spin_unlock_irqrestore (&log->stripe_in_journal_lock, flags);return log->next_checkpoint; } - sh =list_first_entry (&conf->log->stripe_in_journal_list, + sh =list_first_entry (&log->stripe_in_journal_list, struct stripe_head, r5c); new_cp = sh->log_start;spin_unlock_irqrestore (&log->stripe_in_journal_lock, flags);
@@ -1399,7 +1402,7 @@ void r5c_flush_cache(struct r5conf *conf, int num)struct stripe_head *sh, *next;lockdep_assert_held (&conf->device_lock); -if (!conf->log) +if (!READ_ONCE (conf->log))return ; count =0 ;
@@ -1420,7 +1423,7 @@ void r5c_flush_cache(struct r5conf *conf, int num)static void r5c_do_reclaim (struct r5conf *conf) { -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);struct stripe_head *sh;int count =0 ;unsigned long flags;
@@ -1549,7 +1552,7 @@ static void r5l_reclaim_thread(struct md_thread *thread) {struct mddev *mddev = thread->mddev;struct r5conf *conf = mddev->private; -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);if (!log)return ;
@@ -1589,7 +1592,7 @@ void r5l_quiesce(struct r5l_log *log, int quiesce)bool r5l_log_disk_error (struct r5conf *conf) { -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);/* don't allow write if journal disk is missing */ if (!log)
@@ -2633,7 +2636,7 @@ int r5c_try_caching_write(struct r5conf *conf, struct stripe_head_state *s, int disks) { -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);int i;struct r5dev *dev;int to_cache =0 ;
@@ -2800,7 +2803,7 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,struct stripe_head *sh, struct stripe_head_state *s) { - struct r5l_log *log = conf->log; + struct r5l_log *log = READ_ONCE(conf->log);int i;int do_wakeup =0 ;sector_t tree_index;
@@ -2939,7 +2942,7 @@ int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh)/* check whether this big stripe is in write back cache. */ bool r5c_big_stripe_cached (struct r5conf *conf,sector_t sect) { -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);sector_t tree_index;void *slot;
@@ -3047,14 +3050,14 @@ int r5l_start(struct r5l_log *log)void r5c_update_on_rdev_error (struct mddev *mddev,struct md_rdev *rdev) {struct r5conf *conf = mddev->private; -struct r5l_log *log = conf->log; +struct r5l_log *log =READ_ONCE (conf->log);if (!log)return ;if ((raid5_calc_degraded (conf) >0 ||test_bit (Journal, &rdev->flags)) && - conf->log->r5c_journal_mode ==R5C_JOURNAL_MODE_WRITE_BACK ) + log->r5c_journal_mode ==R5C_JOURNAL_MODE_WRITE_BACK )schedule_work (&log->disable_writeback_work); }
@@ -3143,7 +3146,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)spin_lock_init (&log->stripe_in_journal_lock);atomic_set (&log->stripe_in_journal_count,0 ); - conf->log = log; +WRITE_ONCE (conf->log, log);set_bit (MD_HAS_JOURNAL , &conf->mddev->flags);return 0 ;
@@ -3171,7 +3174,7 @@ void r5l_exit_log(struct r5conf *conf)* 'reconfig_mutex' is held by caller, set 'confg->log' to NULL to * ensure disable_writeback_work wakes up and exits. */ - conf->log =NULL ; +WRITE_ONCE (conf->log,NULL );wake_up (&conf->mddev->sb_wait);flush_work (&log->disable_writeback_work);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 133/321 binfmt_misc: cleanup on filesystem umount
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
[ Upstream commit 1c5976ef0f7ad76319df748ccb99a4c7ba2ba464 ]
Currently, registering a new binary type pins the binfmt_misc filesystem. Specifically, this means that as long as there is at least one binary type registered the binfmt_misc filesystem survives all umounts, i.e. the superblock is not destroyed. Meaning that a umount followed by another mount will end up with the same superblock and the same binary type handlers. This is a behavior we tend to discourage for any new filesystems (apart from a few special filesystems such as e.g. configfs or debugfs). A umount operation without the filesystem being pinned - by e.g. someone holding a file descriptor to an open file - should usually result in the destruction of the superblock and all associated resources. This makes introspection easier and leads to clearly defined, simple and clean semantics. An administrator can rely on the fact that a umount will guarantee a clean slate making it possible to reinitialize a filesystem. Right now all binary types would need to be explicitly deleted before that can happen.
This allows us to remove the heavy-handed calls to simple_pin_fs() and simple_release_fs() when creating and deleting binary types. This in turn allows us to replace the current brittle pinning mechanism abusing dget() which has caused a range of bugs judging from prior fixes in [2] and [3]. The additional dget() in load_misc_binary() pins the dentry but only does so for the sake to prevent ->evict_inode() from freeing the node when a user removes the binary type and kill_node() is run. Which would mean ->interpreter and ->interp_file would be freed causing a UAF.
This isn't really nicely documented nor is it very clean because it relies on simple_pin_fs() pinning the filesystem as long as at least one binary type exists. Otherwise it would cause load_misc_binary() to hold on to a dentry belonging to a superblock that has been shutdown. Replace that implicit pinning with a clean and simple per-node refcount and get rid of the ugly dget() pinning. A similar mechanism exists for e.g. binderfs (cf. [4]). All the cleanup work can now be done in ->evict_inode().
In a follow-up patch we will make it possible to use binfmt_misc in sandboxes. We will use the cleaner semantics where a umount for the filesystem will cause the superblock and all resources to be deallocated. In preparation for this apply the same semantics to the initial binfmt_misc mount. Note, that this is a user-visible change and as such a uapi change but one that we can reasonably risk. We've discussed this in earlier versions of this patchset (cf. [1]).
The main user and provider of binfmt_misc is systemd. Systemd provides binfmt_misc via autofs since it is configurable as a kernel module and is used by a few exotic packages and users. As such a binfmt_misc mount is triggered when /proc/sys/fs/binfmt_misc is accessed and is only provided on demand. Other autofs on demand filesystems include EFI ESP which systemd umounts if the mountpoint stays idle for a certain amount of time. This doesn't apply to the binfmt_misc autofs mount which isn't touched once it is mounted meaning this change can't accidently wipe binary type handlers without someone having explicitly unmounted binfmt_misc. After speaking to systemd folks they don't expect this change to affect them.
In line with our general policy, if we see a regression for systemd or other users with this change we will switch back to the old behavior for the initial binfmt_misc mount and have binary types pin the filesystem again. But while we touch this code let's take the chance and let's improve on the status quo.
[1]: https://lore.kernel.org/r/[email protected]
[2]: commit 43a4f2619038 ("exec: binfmt_misc: fix race between load_misc_binary() and kill_node()" [3]: commit 83f918274e4b ("exec: binfmt_misc: shift filp_close(interp_file) from kill_node() to bm_evict_inode()") [4]: commit f0fe2c0f050d ("binder: prevent UAF for binderfs devices II")
---
/* v2 */
- Christian Brauner <[email protected]>:
- Add more comments that explain what's going on.
- Rename functions while changing them to better reflect what they are doing to make the code easier to understand.
- In the first version when a specific binary type handler was removed either through a write to the entry's file or all binary type handlers were removed by a write to the binfmt_misc mount's status file all cleanup work happened during inode eviction. That includes removal of the relevant entries from entry list. While that works fine I disliked that model after thinking about it for a bit. Because it means that there was a window were someone has already removed a or all binary handlers but they could still be safely reached from load_misc_binary() when it has managed to take the read_lock() on the entries list while inode eviction was already happening. Again, that perfectly benign but it's cleaner to remove the binary handler from the list immediately meaning that ones the write to then entry's file or the binfmt_misc status file returns the binary type cannot be executed anymore. That gives stronger guarantees to the user.
--- fs/binfmt_misc.c | 216 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 168 insertions(+), 48 deletions(-)
fs/binfmt_misc.c +168 -48
@@ -60,12 +60,11 @@ typedef struct {char *name;struct dentry *dentry;struct file *interp_file; +refcount_t users;/* sync removal with load_misc_binary() */ } Node;static DEFINE_RWLOCK (entries_lock);static struct file_system_type bm_fs_type; -static struct vfsmount *bm_mnt; -static int entry_count;/* * Max length of the register string. Determined by:
@@ -82,19 +81,23 @@ static int entry_count;*/ #define MAX_REGISTER_LENGTH 1920 -/* -* Check if we support the binfmt -* if we do, return the node, else NULL -* locking is done in load_misc_binary +/** +* search_binfmt_handler - search for a binary handler for @bprm +* @misc: handle to binfmt_misc instance +* @bprm: binary for which we are looking for a handler +* +* Search for a binary type handler for @bprm in the list of registered binary +* type handlers. +* +* Return: binary type list entry on success, NULL on failure */ -static Node *check_file (struct linux_binprm *bprm) +static Node *search_binfmt_handler (struct linux_binprm *bprm) {char *p =strrchr (bprm->interp,'.' ); -struct list_head *l; +Node *e;/* Walk all the registered handlers. */ -list_for_each (l, &entries) { -Node *e =list_entry (l, Node, list); +list_for_each_entry (e, &entries, list) {char *s;int j;
@@ -123,9 +126,49 @@ static Node *check_file(struct linux_binprm *bprm)if (j == e->size)return e; } +return NULL ; } +/** +* get_binfmt_handler - try to find a binary type handler +* @misc: handle to binfmt_misc instance +* @bprm: binary for which we are looking for a handler +* +* Try to find a binfmt handler for the binary type. If one is found take a +* reference to protect against removal via bm_{entry,status}_write(). +* +* Return: binary type list entry on success, NULL on failure +*/ +static Node *get_binfmt_handler (struct linux_binprm *bprm) +{ +Node *e; + +read_lock (&entries_lock); + e =search_binfmt_handler (bprm); +if (e) +refcount_inc (&e->users); +read_unlock (&entries_lock); +return e; +} + +/** +* put_binfmt_handler - put binary handler node +* @e: node to put +* +* Free node syncing with load_misc_binary() and defer final free to +* load_misc_binary() in case it is using the binary type handler we were +* requested to remove. +*/ +static void put_binfmt_handler (Node *e) +{ +if (refcount_dec_and_test (&e->users)) { +if (e->flags &MISC_FMT_OPEN_FILE ) +filp_close (e->interp_file,NULL ); +kfree (e); + } +} +/* * the loader itself */
@@ -139,12 +182,7 @@ static int load_misc_binary(struct linux_binprm *bprm)if (!enabled)return retval; -/* to keep locking time low, we copy the interpreter string */ -read_lock (&entries_lock); - fmt =check_file (bprm); -if (fmt) -dget (fmt->dentry); -read_unlock (&entries_lock); + fmt =get_binfmt_handler (bprm);if (!fmt)return retval;
@@ -198,7 +236,16 @@ static int load_misc_binary(struct linux_binprm *bprm) retval =0 ; ret: -dput (fmt->dentry); + +/* +* If we actually put the node here all concurrent calls to +* load_misc_binary() will have finished. We also know +* that for the refcount to be zero ->evict_inode() must have removed +* the node to be deleted from the list. All that is left for us is to +* close and free. +*/ +put_binfmt_handler (fmt); +return retval; }
@@ -553,30 +600,90 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)return inode; } +/** +* bm_evict_inode - cleanup data associated with @inode +* @inode: inode to which the data is attached +* +* Cleanup the binary type handler data associated with @inode if a binary type +* entry is removed or the filesystem is unmounted and the super block is +* shutdown. +* +* If the ->evict call was not caused by a super block shutdown but by a write +* to remove the entry or all entries via bm_{entry,status}_write() the entry +* will have already been removed from the list. We keep the list_empty() check +* to make that explicit. +*/ static void bm_evict_inode (struct inode *inode) {Node *e = inode->i_private; -if (e && e->flags &MISC_FMT_OPEN_FILE ) -filp_close (e->interp_file,NULL ); -clear_inode (inode); -kfree (e); + +if (e) { +write_lock (&entries_lock); +if (!list_empty (&e->list)) +list_del_init (&e->list); +write_unlock (&entries_lock); +put_binfmt_handler (e); + } } -static void kill_node (Node *e) +/** +* unlink_binfmt_dentry - remove the dentry for the binary type handler +* @dentry: dentry associated with the binary type handler +* +* Do the actual filesystem work to remove a dentry for a registered binary +* type handler. Since binfmt_misc only allows simple files to be created +* directly under the root dentry of the filesystem we ensure that we are +* indeed passed a dentry directly beneath the root dentry, that the inode +* associated with the root dentry is locked, and that it is a regular file we +* are asked to remove. +*/ +static void unlink_binfmt_dentry (struct dentry *dentry) { -struct dentry *dentry; +struct dentry *parent = dentry->d_parent; +struct inode *inode, *parent_inode; + +/* All entries are immediate descendants of the root dentry. */ +if (WARN_ON_ONCE (dentry->d_sb->s_root != parent)) +return ; +/* We only expect to be called on regular files. */ + inode =d_inode (dentry); +if (WARN_ON_ONCE (!S_ISREG (inode->i_mode))) +return ; + +/* The parent inode must be locked. */ + parent_inode =d_inode (parent); +if (WARN_ON_ONCE (!inode_is_locked (parent_inode))) +return ; + +if (simple_positive (dentry)) { +dget (dentry); +simple_unlink (parent_inode, dentry); +d_delete (dentry); +dput (dentry); + } +} + +/** +* remove_binfmt_handler - remove a binary type handler +* @misc: handle to binfmt_misc instance +* @e: binary type handler to remove +* +* Remove a binary type handler from the list of binary type handlers and +* remove its associated dentry. This is called from +* binfmt_{entry,status}_write(). In the future, we might want to think about +* adding a proper ->unlink() method to binfmt_misc instead of forcing caller's +* to use writes to files in order to delete binary type handlers. But it has +* worked for so long that it's not a pressing issue. +*/ +static void remove_binfmt_handler (Node *e) +{write_lock (&entries_lock);list_del_init (&e->list);write_unlock (&entries_lock); - - dentry = e->dentry; -drop_nlink (d_inode (dentry)); -d_drop (dentry); -dput (dentry); -simple_release_fs (&bm_mnt, &entry_count); +unlink_binfmt_dentry (e->dentry); }/* /<entry> */
@@ -603,8 +710,8 @@ bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)static ssize_t bm_entry_write (struct file *file,const char __user *buffer,size_t count,loff_t *ppos) { -struct dentry *root; -Node *e =file_inode (file)->i_private; +struct inode *inode =file_inode (file); +Node *e = inode->i_private;int res =parse_command (buffer, count);switch (res) {
@@ -618,13 +725,22 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,break ;case 3 :/* Delete this handler. */ - root =file_inode (file)->i_sb->s_root; -inode_lock (d_inode (root)); + inode =d_inode (inode->i_sb->s_root); +inode_lock (inode); +/* +* In order to add new element or remove elements from the list +* via bm_{entry,register,status}_write() inode_lock() on the +* root inode must be held. +* The lock is exclusive ensuring that the list can't be +* modified. Only load_misc_binary() can access but does so +* read-only. So we only need to take the write lock when we +* actually remove the entry from the list. +*/ if (!list_empty (&e->list)) -kill_node (e); +remove_binfmt_handler (e); -inode_unlock (d_inode (root)); +inode_unlock (inode);break ;default :return res;
@@ -683,13 +799,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,if (!inode) goto out2; - err =simple_pin_fs (&bm_fs_type, &bm_mnt, &entry_count); -if (err) { -iput (inode); - inode =NULL ; - goto out2; - } - +refcount_set (&e->users,1 ); e->dentry =dget (dentry); inode->i_private = e; inode->i_fop = &bm_entry_operations;
@@ -733,7 +843,8 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { int res = parse_command(buffer, count); -struct dentry *root; +Node *e, *next; +struct inode *inode;switch (res) {case 1 :
@@ -746,13 +857,22 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,break ;case 3 :/* Delete all handlers. */ - root =file_inode (file)->i_sb->s_root; -inode_lock (d_inode (root)); + inode =d_inode (file_inode (file)->i_sb->s_root); +inode_lock (inode); -while (!list_empty (&entries)) -kill_node (list_first_entry (&entries, Node, list)); +/* +* In order to add new element or remove elements from the list +* via bm_{entry,register,status}_write() inode_lock() on the +* root inode must be held. +* The lock is exclusive ensuring that the list can't be +* modified. Only load_misc_binary() can access but does so +* read-only. So we only need to take the write lock when we +* actually remove the entry from the list. +*/ +list_for_each_entry_safe (e, next, &entries, list) +remove_binfmt_handler (e); -inode_unlock (d_inode (root)); +inode_unlock (inode);break ;default :return res;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 134/321 drm/tegra: Zero-initialize iosys_map
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <[email protected]>
[ Upstream commit 3868ff006b572cf501a3327832d36c64a9eca86a ]
UBSAN reports an invalid load for bool, as the iosys_map is read later without being initialized. Zero-initialize it to avoid this.
--- drivers/gpu/drm/tegra/gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/tegra/gem.c +1 -1
@@ -175,7 +175,7 @@ static void tegra_bo_unpin(struct host1x_bo_mapping *map)static void *tegra_bo_mmap (struct host1x_bo *bo) {struct tegra_bo *obj =host1x_to_tegra_bo (bo); -struct iosys_map map; +struct iosys_map map = {0 };int ret;if (obj->vaddr) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 135/321 media: qcom: venus: fix incorrect return value
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil <[email protected]>
[ Upstream commit 51b74c09ac8c5862007fc2bf0d465529d06dd446 ]
'pd' can be NULL, and in that case it shouldn't be passed to PTR_ERR. Fixes a smatch warning:
drivers/media/platform/qcom/venus/pm_helpers.c:873 vcodec_domains_get() warn: passing zero to 'PTR_ERR'
--- drivers/media/platform/qcom/venus/pm_helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/qcom/venus/pm_helpers.c +1 -1
@@ -870,7 +870,7 @@ static int vcodec_domains_get(struct venus_core *core) pd =dev_pm_domain_attach_by_name (dev, res->vcodec_pmdomains[i]);if (IS_ERR_OR_NULL (pd)) -return PTR_ERR (pd) ? : -ENODATA ; +return pd ?PTR_ERR (pd) : -ENODATA ; core->pmdomains[i] = pd; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 136/321 scsi: spi: Fix sshdr use
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit 0b149cee836aa53989ea089af1cb9d90d7c6ac9e ]
If scsi_execute_cmd returns < 0, it doesn't initialize the sshdr, so we shouldn't access the sshdr. If it returns 0, then the cmd executed successfully, so there is no need to check the sshdr. This has us access the sshdr when we get a return value > 0.
--- drivers/scsi/scsi_transport_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/scsi_transport_spi.c +2 -2
@@ -677,10 +677,10 @@ spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,for (r =0 ; r < retries; r++) { result =spi_execute (sdev, spi_write_buffer,DMA_TO_DEVICE , buffer, len, &sshdr); -if (result || !scsi_device_online (sdev)) { +if (result || !scsi_device_online (sdev)) {scsi_device_set_state (sdev,SDEV_QUIESCE ); -if (scsi_sense_valid (&sshdr) +if (result >0 &&scsi_sense_valid (&sshdr) && sshdr.sense_key ==ILLEGAL_REQUEST /* INVALID FIELD IN CDB */ && sshdr.asc ==0x24 && sshdr.ascq ==0x00 )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 137/321 gfs2: setattr_chown: Add missing initialization
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit 2d8d7990619878a848b1d916c2f936d3012ee17d ]
Add a missing initialization of variable ap in setattr_chown(). Without, chown() may be able to bypass quotas.
--- fs/gfs2/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/gfs2/inode.c +1 -1
@@ -1907,7 +1907,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)kuid_t ouid, nuid;kgid_t ogid, ngid;int error; -struct gfs2_alloc_parms ap; +struct gfs2_alloc_parms ap = {}; ouid = inode->i_uid; ogid = inode->i_gid;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 138/321 wifi: iwlwifi: abort scan when rfkill on but device enabled
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miri Korenblit <[email protected]>
[ Upstream commit 3c6a0b1f0add72e7f522bc9145222b86d0a7712a ]
In RFKILL we first set the RFKILL bit, then we abort scan (if one exists) by waiting for the notification from FW
and notifying mac80211. And then we stop the device.
But in case we have a scan ongoing in the period of time between rfkill on and before the device is stopped - we will not wait for the FW notification because of the iwl_mvm_is_radio_killed() condition, and then the scan_status and uid_status are misconfigured, (scan_status is cleared but uid_status not)
and when the notification suddenly arrives (before stopping the device) we will get into the assert about scan_status and uid_status mismatch. Fix this by waiting for FW notif when rfkill is on but the device isn't disabled yet.
--- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/mvm/scan.c +1 -1
@@ -3226,7 +3226,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)if (!(mvm->scan_status & type))return 0 ; -if (iwl_mvm_is_radio_killed (mvm)) { +if (!test_bit (STATUS_DEVICE_ENABLED , &mvm->trans->status)) { ret =0 ; goto out; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 139/321 wifi: iwlwifi: fw: Fix debugfs command sending
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mukesh Sisodiya <[email protected]>
[ Upstream commit 048449fc666d736a1a17d950fde0b5c5c8fd10cc ]
During debugfs command handling transport function is used directly, this bypasses the locking used by runtime operation function and leads to a kernel warning when two commands are
sent in parallel.
Fix it by using runtime operations function when sending debugfs command.
--- drivers/net/wireless/intel/iwlwifi/fw/debugfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +5 -1
@@ -163,7 +163,11 @@ static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt, event_cfg.enabled_severities =cpu_to_le32 (enabled_severities); - ret =iwl_trans_send_cmd (fwrt->trans, &hcmd); +if (fwrt->ops && fwrt->ops->send_hcmd) + ret = fwrt->ops->send_hcmd (fwrt->ops_ctx, &hcmd); +else + ret = -EPERM ; +IWL_INFO (fwrt,"sent host event cfg with enabled_severities: %u, ret: %d\n" , enabled_severities, ret);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 140/321 clk: visconti: Add bounds-checking coverage for struct visconti_pll_provider
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gustavo A. R. Silva <[email protected]>
[ Upstream commit 397d887c1601a71e8a8abdb6beea67d58f0472d3 ]
In order to gain the bounds-checking coverage that __counted_by provides to flexible-array members at run-time via CONFIG_UBSAN_BOUNDS (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions), we must make sure that the counter member, in this particular case num, is updated before the first access to the flex-array member, in this particular case array hws. See below:
commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") introduced __counted_by for struct clk_hw_onecell_data together with changes to relocate some of assignments of counter num before hws is accessed:
include/linux/clk-provider.h:
1380 struct clk_hw_onecell_data {
1381 unsigned int num;
1382 struct clk_hw *hws[] __counted_by(num);
1383 };
However, this structure is used as a member in other structs, in this case in struct visconti_pll_provider:
drivers/clk/visconti/pll.h:
16 struct visconti_pll_provider {
17 void __iomem *reg_base;
18 struct device_node *node;
19
20 /* Must be last */
21 struct clk_hw_onecell_data clk_data;
22 };
Hence, we need to move the assignments to ctx->clk_data.num after allocation for struct visconti_pll_provider and before accessing the flexible array ctx->clk_data.hws. And, as assignments for all members in struct visconti_pll_provider are originally adjacent to each other, relocate all assignments together, so we don't split up ctx->clk_data.hws = nr_plls from the rest. :)
--- drivers/clk/visconti/pll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/clk/visconti/pll.c +3 -3
@@ -329,12 +329,12 @@ struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,if (!ctx)return ERR_PTR (-ENOMEM ); -for (i =0 ; i < nr_plls; ++i) - ctx->clk_data.hws[i] =ERR_PTR (-ENOENT ); - ctx->node = np; ctx->reg_base = base; ctx->clk_data.num = nr_plls; +for (i =0 ; i < nr_plls; ++i) + ctx->clk_data.hws[i] =ERR_PTR (-ENOENT ); +return ctx; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 141/321 IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <[email protected]>
[ Upstream commit 2f19c4b8395ccb6eb25ccafee883c8cfbe3fc193 ]
handle_receive_interrupt_napi_sp() running inside interrupt handler could introduce inverse lock ordering between &dd->irq_src_lock and &dd->uctxt_lock, if read_mod_write() is preempted by the isr.
[CPU0] | [CPU1]
hfi1_ipoib_dev_open() |
--> hfi1_netdev_enable_queues() |
--> enable_queues(rx) |
--> hfi1_rcvctrl() |
--> set_intr_bits() |
--> read_mod_write() |
--> spin_lock(&dd->irq_src_lock) |
| hfi1_poll()
| --> poll_next()
| --> spin_lock_irq(&dd->uctxt_lock)
|
| --> hfi1_rcvctrl()
| --> set_intr_bits()
| --> read_mod_write()
| --> spin_lock(&dd->irq_src_lock)
<interrupt> |
--> handle_receive_interrupt_napi_sp() |
--> set_all_fastpath() |
--> hfi1_rcd_get_by_index() |
--> spin_lock_irqsave(&dd->uctxt_lock) |This flaw was found by an experimental static analysis tool I am developing for irq-related deadlock.
To prevent the potential deadlock, the patch use spin_lock_irqsave() on &dd->irq_src_lock inside read_mod_write() to prevent the possible deadlock scenario.
--- drivers/infiniband/hw/hfi1/chip.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +3 -2
@@ -13183,15 +13183,16 @@ static void read_mod_write(struct hfi1_devdata *dd, u16 src, u64 bits, {u64 reg;u16 idx = src /BITS_PER_REGISTER ; +unsigned long flags; -spin_lock (&dd->irq_src_lock); +spin_lock_irqsave (&dd->irq_src_lock, flags); reg =read_csr (dd,CCE_INT_MASK + (8 * idx));if (set) reg |= bits;else reg &= ~bits;write_csr (dd,CCE_INT_MASK + (8 * idx), reg); -spin_unlock (&dd->irq_src_lock); +spin_unlock_irqrestore (&dd->irq_src_lock, flags); }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 142/321 hwmon: (ltc2992) Avoid division by zero
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Antoniu Miclaus <[email protected]>
[ Upstream commit 10b02902048737f376104bc69e5212466e65a542 ]
Do not allow setting shunt resistor to 0. This results in a division by zero when performing current value computations based on input voltages and connected resistor values.
--- drivers/hwmon/ltc2992.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/hwmon/ltc2992.c +5 -1
@@ -875,8 +875,12 @@ static int ltc2992_parse_dt(struct ltc2992_state *st) } ret =fwnode_property_read_u32 (child,"shunt-resistor-micro-ohms" , &val); -if (!ret) +if (!ret) { +if (!val) +return dev_err_probe (&st->client->dev, -EINVAL , +"shunt resistor value cannot be zero\n" ); st->r_sense_uohm[addr] = val; + } }return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 143/321 kbuild: rust_is_available: normalize version matching
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Ojeda <[email protected]>
[ Upstream commit 7cd6a3e1f94bab4f2a3425e06f70ab13eb8190d4 ]
In order to match the version string, sed is used in a couple cases, and grep and head in a couple others.
Make the script more consistent and easier to understand by using the same method, sed, for all of them.
This makes the version matching also a bit more strict for the changed cases, since the strings rustc and bindgen will now be required, which should be fine since rustc complains if one attempts to call it with another program name, and bindgen uses a hardcoded string.
In addition, clarify why one of the existing sed commands does not provide an address like the others.
Stable-dep-of: 5ce86c6c8613 ("rust: suppress error messages from CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT")
--- scripts/rust_is_available.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
scripts/rust_is_available.sh +5 -4
@@ -40,8 +40,7 @@ fi # Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. rust_compiler_version=$( \ LC_ALL=C "$RUSTC" --version 2>/dev/null \ - | head -n 1 \ - | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' \ + | sed -nE '1s:.*rustc ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' ) rust_compiler_min_version=$($min_tool_version rustc) rust_compiler_cversion=$(get_canonical_version $rust_compiler_version)
@@ -67,8 +66,7 @@ fi # Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. rust_bindings_generator_version=$( \ LC_ALL=C "$BINDGEN" --version 2>/dev/null \ - | head -n 1 \ - | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' \ + | sed -nE '1s:.*bindgen ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' ) rust_bindings_generator_min_version=$($min_tool_version bindgen) rust_bindings_generator_cversion=$(get_canonical_version $rust_bindings_generator_version)
@@ -110,6 +108,9 @@ fi # `bindgen` returned successfully, thus use the output to check that the version # of the `libclang` found by the Rust bindings generator is suitable. +# +# Unlike other version checks, note that this one does not necessarily appear +# in the first line of the output, thus no `sed` address is provided. bindgen_libclang_version=$( \ echo "$bindgen_libclang_output" \ | sed -nE 's:.*clang version ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p'
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 144/321 kbuild: rust_is_available: handle failures calling `$RUSTC`/`$BINDGEN`
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Ojeda <[email protected]>
[ Upstream commit f295522886a4ebb628cadb2cd74d0661d6292978 ]
The script already checks if $RUSTC and $BINDGEN exists via command, but the environment variables may point to a non-executable file, or the programs may fail for some other reason. While the script successfully exits with a failure as it should, the error given can be quite confusing depending on the shell and the behavior of its command. For instance, with dash:
$ RUSTC=./mm BINDGEN=bindgen CC=clang scripts/rust_is_available.sh
scripts/rust_is_available.sh: 19: arithmetic expression: expecting primary: "100000 * + 100 * + "Thus detect failure exit codes when calling $RUSTC and $BINDGEN and print a better message, in a similar way to what we do when extracting the libclang version found by bindgen.
Stable-dep-of: 5ce86c6c8613 ("rust: suppress error messages from CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT")
--- scripts/rust_is_available.sh | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
scripts/rust_is_available.sh +26 -2
@@ -38,8 +38,20 @@ fi # Check that the Rust compiler version is suitable. # # Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. +rust_compiler_output=$( \ + LC_ALL=C "$RUSTC" --version 2>/dev/null +) || rust_compiler_code=$? +if [ -n "$rust_compiler_code" ]; then + echo >&2 "***" + echo >&2 "*** Running '$RUSTC' to check the Rust compiler version failed with" + echo >&2 "*** code $rust_compiler_code. See output and docs below for details:" + echo >&2 "***" + echo >&2 "$rust_compiler_output" + echo >&2 "***" + exit 1 +fi rust_compiler_version=$( \ - LC_ALL=C "$RUSTC" --version 2>/dev/null \ + echo "$rust_compiler_output" \ | sed -nE '1s:.*rustc ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' ) rust_compiler_min_version=$($min_tool_version rustc)
@@ -64,8 +76,20 @@ fi # Check that the Rust bindings generator is suitable. # # Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. +rust_bindings_generator_output=$( \ + LC_ALL=C "$BINDGEN" --version 2>/dev/null +) || rust_bindings_generator_code=$? +if [ -n "$rust_bindings_generator_code" ]; then + echo >&2 "***" + echo >&2 "*** Running '$BINDGEN' to check the Rust bindings generator version failed with" + echo >&2 "*** code $rust_bindings_generator_code. See output and docs below for details:" + echo >&2 "***" + echo >&2 "$rust_bindings_generator_output" + echo >&2 "***" + exit 1 +fi rust_bindings_generator_version=$( \ - LC_ALL=C "$BINDGEN" --version 2>/dev/null \ + echo "$rust_bindings_generator_output" \ | sed -nE '1s:.*bindgen ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' ) rust_bindings_generator_min_version=$($min_tool_version bindgen)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 145/321 rust: work around `bindgen` 0.69.0 issue
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Ojeda <[email protected]>
[ Upstream commit 9e98db17837093cb0f4dcfcc3524739d93249c45 ]
bindgen 0.69.0 contains a bug: --version does not work without providing a header [1]:
error: the following required arguments were not provided:
<HEADER>
Usage: bindgen <FLAGS> <OPTIONS> <HEADER> -- <CLANG_ARGS>...
Thus, in preparation for supporting several bindgen versions, work around the issue by passing a dummy argument.
Include a comment so that we can remove the workaround in the future.
Stable-dep-of: 5ce86c6c8613 ("rust: suppress error messages from CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT")
--- init/Kconfig | 5 ++++- scripts/rust_is_available.sh | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-)
init/Kconfig +4 -1
@@ -1947,7 +1947,10 @@ config RUSTC_VERSION_TEXT config BINDGEN_VERSION_TEXT string depends on RUST - default $(shell,command -v $(BINDGEN) >/dev/null 2>&1 && $(BINDGEN) --version || echo n) + # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 + # (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when + # the minimum version is upgraded past that (0.69.1 already fixed the issue). + default $(shell,command -v $(BINDGEN) >/dev/null 2>&1 && $(BINDGEN) --version workaround-for-0.69.0 || echo n) # # Place an empty function call at each tracepoint site. Can be
scripts/rust_is_available.sh +5 -1
@@ -76,8 +76,12 @@ fi # Check that the Rust bindings generator is suitable. # # Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. +# +# The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 +# (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when +# the minimum version is upgraded past that (0.69.1 already fixed the issue). rust_bindings_generator_output=$( \ - LC_ALL=C "$BINDGEN" --version 2>/dev/null + LC_ALL=C "$BINDGEN" --version workaround-for-0.69.0 2>/dev/null ) || rust_bindings_generator_code=$? if [ -n "$rust_bindings_generator_code" ]; then echo >&2 "***"
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 146/321 rust: suppress error messages from CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada <[email protected]>
[ Upstream commit 5ce86c6c861352c9346ebb5c96ed70cb67414aa3 ]
While this is a somewhat unusual case, I encountered odd error messages when I ran Kconfig in a foreign architecture chroot.
$ make allmodconfig sh: 1: rustc: not found sh: 1: bindgen: not found # # configuration written to .config #
The successful execution of 'command -v rustc' does not necessarily mean that 'rustc --version' will succeed.
$ sh -c 'command -v rustc' /home/masahiro/.cargo/bin/rustc $ sh -c 'rustc --version' sh: 1: rustc: not found
Here, 'rustc' is built for x86, and I ran it in an arm64 system.
The current code:
command -v $(RUSTC) >/dev/null 2>&1 && $(RUSTC) --version || echo n
can be turned into:
command -v $(RUSTC) >/dev/null 2>&1 && $(RUSTC) --version 2>/dev/null || echo n
However, I did not understand the necessity of 'command -v $(RUSTC)'.
I simplified it to:
$(RUSTC) --version 2>/dev/null || echo n
--- init/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
init/Kconfig +2 -2
@@ -1942,7 +1942,7 @@ config RUST config RUSTC_VERSION_TEXT string depends on RUST - default $(shell,command -v $(RUSTC) >/dev/null 2>&1 && $(RUSTC) --version || echo n) + default $(shell,$(RUSTC) --version 2>/dev/null || echo n) config BINDGEN_VERSION_TEXT string
@@ -1950,7 +1950,7 @@ config BINDGEN_VERSION_TEXT # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 # (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when # the minimum version is upgraded past that (0.69.1 already fixed the issue). - default $(shell,command -v $(BINDGEN) >/dev/null 2>&1 && $(BINDGEN) --version workaround-for-0.69.0 || echo n) + default $(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null || echo n) # # Place an empty function call at each tracepoint site. Can be
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 147/321 rust: fix the default format for CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada <[email protected]>
[ Upstream commit aacf93e87f0d808ef46e621aa56caea336b4433c ]
Another oddity in these config entries is their default value can fall back to 'n', which is a value for bool or tristate symbols.
The '|| echo n' is an incorrect workaround to avoid the syntax error. This is not a big deal, as the entry is hidden by 'depends on RUST' in situations where '$(RUSTC) --version' or '$(BINDGEN) --version' fails. Anyway, it looks odd.
The default of a string type symbol should be a double-quoted string literal. Turn it into an empty string when the version command fails.
--- init/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
init/Kconfig +2 -2
@@ -1942,7 +1942,7 @@ config RUST config RUSTC_VERSION_TEXT string depends on RUST - default $(shell,$(RUSTC) --version 2>/dev/null || echo n) + default "$(shell,$(RUSTC) --version 2>/dev/null)" config BINDGEN_VERSION_TEXT string
@@ -1950,7 +1950,7 @@ config BINDGEN_VERSION_TEXT # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 # (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when # the minimum version is upgraded past that (0.69.1 already fixed the issue). - default $(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null || echo n) + default "$(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null)" # # Place an empty function call at each tracepoint site. Can be
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 148/321 arm64: Fix KASAN random tag seed initialization
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Holland <[email protected]>
[ Upstream commit f75c235565f90c4a17b125e47f1c68ef6b8c2bce ]
Currently, kasan_init_sw_tags() is called before setup_per_cpu_areas(), so per_cpu(prng_state, cpu) accesses the same address regardless of the value of "cpu", and the same seed value gets copied to the percpu area for every CPU. Fix this by moving the call to smp_prepare_boot_cpu(), which is the first architecture hook after setup_per_cpu_areas().
--- arch/arm64/kernel/setup.c | 3 --- arch/arm64/kernel/smp.c | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-)
arch/arm64/kernel/setup.c +0 -3
@@ -360,9 +360,6 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)smp_init_cpus ();smp_build_mpidr_hash (); -/* Init percpu seeds for random tags after cpus are set up. */ -kasan_init_sw_tags (); -#ifdef CONFIG_ARM64_SW_TTBR0_PAN /* * Make sure init_thread_info.ttbr0 always generates translation
arch/arm64/kernel/smp.c +2 -0
@@ -464,6 +464,8 @@ void __init smp_prepare_boot_cpu(void)init_gic_priority_masking ();kasan_init_hw_tags (); +/* Init percpu seeds for random tags after cpus are set up. */ +kasan_init_sw_tags (); }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 149/321 block: Fix lockdep warning in blk_mq_mark_tag_wait
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Lingfeng <[email protected]>
[ Upstream commit b313a8c835516bdda85025500be866ac8a74e022 ]
Lockdep reported a warning in Linux version 6.6:
[ 414.344659] ================================
[ 414.345155] WARNING: inconsistent lock state
[ 414.345658] 6.6.0-07439-gba2303cacfda #6 Not tainted
[ 414.346221] --------------------------------
[ 414.346712] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
[ 414.347545] kworker/u10:3/1152 [HC0[0]:SC0[0]:HE0:SE1] takes:
[ 414.349245] ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
[ 414.351204] {IN-SOFTIRQ-W} state was registered at:
[ 414.351751] lock_acquire+0x18d/0x460
[ 414.352218] _raw_spin_lock_irqsave+0x39/0x60
[ 414.352769] __wake_up_common_lock+0x22/0x60
[ 414.353289] sbitmap_queue_wake_up+0x375/0x4f0
[ 414.353829] sbitmap_queue_clear+0xdd/0x270
[ 414.354338] blk_mq_put_tag+0xdf/0x170
[ 414.354807] __blk_mq_free_request+0x381/0x4d0
[ 414.355335] blk_mq_free_request+0x28b/0x3e0
[ 414.355847] __blk_mq_end_request+0x242/0xc30
[ 414.356367] scsi_end_request+0x2c1/0x830
[ 414.345155] WARNING: inconsistent lock state
[ 414.345658] 6.6.0-07439-gba2303cacfda #6 Not tainted
[ 414.346221] --------------------------------
[ 414.346712] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
[ 414.347545] kworker/u10:3/1152 [HC0[0]:SC0[0]:HE0:SE1] takes:
[ 414.349245] ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
[ 414.351204] {IN-SOFTIRQ-W} state was registered at:
[ 414.351751] lock_acquire+0x18d/0x460
[ 414.352218] _raw_spin_lock_irqsave+0x39/0x60
[ 414.352769] __wake_up_common_lock+0x22/0x60
[ 414.353289] sbitmap_queue_wake_up+0x375/0x4f0
[ 414.353829] sbitmap_queue_clear+0xdd/0x270
[ 414.354338] blk_mq_put_tag+0xdf/0x170
[ 414.354807] __blk_mq_free_request+0x381/0x4d0
[ 414.355335] blk_mq_free_request+0x28b/0x3e0
[ 414.355847] __blk_mq_end_request+0x242/0xc30
[ 414.356367] scsi_end_request+0x2c1/0x830
[ 414.356863] scsi_io_completion+0x177/0x1610
[ 414.357379] scsi_complete+0x12f/0x260
[ 414.357856] blk_complete_reqs+0xba/0xf0
[ 414.358338] __do_softirq+0x1b0/0x7a2
[ 414.358796] irq_exit_rcu+0x14b/0x1a0
[ 414.359262] sysvec_call_function_single+0xaf/0xc0
[ 414.359828] asm_sysvec_call_function_single+0x1a/0x20
[ 414.360426] default_idle+0x1e/0x30
[ 414.360873] default_idle_call+0x9b/0x1f0
[ 414.361390] do_idle+0x2d2/0x3e0
[ 414.361819] cpu_startup_entry+0x55/0x60
[ 414.362314] start_secondary+0x235/0x2b0
[ 414.362809] secondary_startup_64_no_verify+0x18f/0x19b
[ 414.363413] irq event stamp: 428794
[ 414.363825] hardirqs last enabled at (428793): [<ffffffff816bfd1c>] ktime_get+0x1dc/0x200
[ 414.364694] hardirqs last disabled at (428794): [<ffffffff85470177>] _raw_spin_lock_irq+0x47/0x50
[ 414.365629] softirqs last enabled at (428444): [<ffffffff85474780>] __do_softirq+0x540/0x7a2
[ 414.366522] softirqs last disabled at (428419): [<ffffffff813f65ab>] irq_exit_rcu+0x14b/0x1a0
[ 414.367425]
other info that might help us debug this:
[ 414.368194] Possible unsafe locking scenario:
[ 414.368900] CPU0
[ 414.369225] ----
[ 414.369548] lock(&sbq->ws[i].wait);
[ 414.370000] <Interrupt>
[ 414.370342] lock(&sbq->ws[i].wait);
[ 414.370802]
*** DEADLOCK ***
[ 414.371569] 5 locks held by kworker/u10:3/1152:
[ 414.372088] #0: ffff88810130e938 ((wq_completion)writeback){+.+.}-{0:0}, at: process_scheduled_works+0x357/0x13f0
[ 414.373180] #1: ffff88810201fdb8 ((work_completion)(&(&wb->dwork)->work)){+.+.}-{0:0}, at: process_scheduled_works+0x3a3/0x13f0
[ 414.374384] #2: ffffffff86ffbdc0 (rcu_read_lock){....}-{1:2}, at: blk_mq_run_hw_queue+0x637/0xa00
[ 414.375342] #3: ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
[ 414.376377] #4: ffff888106205a08 (&hctx->dispatch_wait_lock){+.-.}-{2:2}, at: blk_mq_dispatch_rq_list+0x1337/0x1ee0
[ 414.378607]
stack backtrace:
[ 414.379177] CPU: 0 PID: 1152 Comm: kworker/u10:3 Not tainted 6.6.0-07439-gba2303cacfda #6
[ 414.380032] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
[ 414.381177] Workqueue: writeback wb_workfn (flush-253:0)
[ 414.381805] Call Trace:
[ 414.382136] <TASK>
[ 414.382429] dump_stack_lvl+0x91/0xf0
[ 414.382884] mark_lock_irq+0xb3b/0x1260
[ 414.383367] ? __pfx_mark_lock_irq+0x10/0x10
[ 414.383889] ? stack_trace_save+0x8e/0xc0
[ 414.384373] ? __pfx_stack_trace_save+0x10/0x10
[ 414.384903] ? graph_lock+0xcf/0x410
[ 414.385350] ? save_trace+0x3d/0xc70
[ 414.385808] mark_lock.part.20+0x56d/0xa90
[ 414.386317] mark_held_locks+0xb0/0x110
[ 414.386791] ? __pfx_do_raw_spin_lock+0x10/0x10
[ 414.387320] lockdep_hardirqs_on_prepare+0x297/0x3f0
[ 414.387901] ? _raw_spin_unlock_irq+0x28/0x50
[ 414.388422] trace_hardirqs_on+0x58/0x100
[ 414.388917] _raw_spin_unlock_irq+0x28/0x50
[ 414.389422] __blk_mq_tag_busy+0x1d6/0x2a0
[ 414.389920] __blk_mq_get_driver_tag+0x761/0x9f0
[ 414.390899] blk_mq_dispatch_rq_list+0x1780/0x1ee0
[ 414.391473] ? __pfx_blk_mq_dispatch_rq_list+0x10/0x10
[ 414.392070] ? sbitmap_get+0x2b8/0x450
[ 414.392533] ? __blk_mq_get_driver_tag+0x210/0x9f0
[ 414.393095] __blk_mq_sched_dispatch_requests+0xd99/0x1690
[ 414.393730] ? elv_attempt_insert_merge+0x1b1/0x420
[ 414.394302] ? __pfx___blk_mq_sched_dispatch_requests+0x10/0x10
[ 414.394970] ? lock_acquire+0x18d/0x460
[ 414.395456] ? blk_mq_run_hw_queue+0x637/0xa00
[ 414.395986] ? __pfx_lock_acquire+0x10/0x10
[ 414.396499] blk_mq_sched_dispatch_requests+0x109/0x190
[ 414.397100] blk_mq_run_hw_queue+0x66e/0xa00
[ 414.397616] blk_mq_flush_plug_list.part.17+0x614/0x2030
[ 414.398244] ? __pfx_blk_mq_flush_plug_list.part.17+0x10/0x10
[ 414.398897] ? writeback_sb_inodes+0x241/0xcc0
[ 414.399429] blk_mq_flush_plug_list+0x65/0x80
[ 414.399957] __blk_flush_plug+0x2f1/0x530
[ 414.400458] ? __pfx___blk_flush_plug+0x10/0x10
[ 414.400999] blk_finish_plug+0x59/0xa0
[ 414.401467] wb_writeback+0x7cc/0x920
[ 414.401935] ? __pfx_wb_writeback+0x10/0x10
[ 414.402442] ? mark_held_locks+0xb0/0x110
[ 414.402931] ? __pfx_do_raw_spin_lock+0x10/0x10
[ 414.403462] ? lockdep_hardirqs_on_prepare+0x297/0x3f0
[ 414.404062] wb_workfn+0x2b3/0xcf0
[ 414.404500] ? __pfx_wb_workfn+0x10/0x10
[ 414.404989] process_scheduled_works+0x432/0x13f0
[ 414.405546] ? __pfx_process_scheduled_works+0x10/0x10
[ 414.406139] ? do_raw_spin_lock+0x101/0x2a0
[ 414.406641] ? assign_work+0x19b/0x240
[ 414.407106] ? lock_is_held_type+0x9d/0x110
[ 414.407604] worker_thread+0x6f2/0x1160
[ 414.408075] ? __kthread_parkme+0x62/0x210
[ 414.408572] ? lockdep_hardirqs_on_prepare+0x297/0x3f0
[ 414.409168] ? __kthread_parkme+0x13c/0x210
[ 414.409678] ? __pfx_worker_thread+0x10/0x10
[ 414.410191] kthread+0x33c/0x440
[ 414.410602] ? __pfx_kthread+0x10/0x10
[ 414.411068] ret_from_fork+0x4d/0x80
[ 414.411526] ? __pfx_kthread+0x10/0x10
[ 414.411993] ret_from_fork_asm+0x1b/0x30
[ 414.412489] </TASK>When interrupt is turned on while a lock holding by spin_lock_irq it throws a warning because of potential deadlock.
blk_mq_prep_dispatch_rq
blk_mq_get_driver_tag
__blk_mq_get_driver_tag
__blk_mq_alloc_driver_tag
blk_mq_tag_busy -> tag is already busy
// failed to get driver tag blk_mq_mark_tag_wait
spin_lock_irq(&wq->lock) -> lock A (&sbq->ws[i].wait) __add_wait_queue(wq, wait) -> wait queue active blk_mq_get_driver_tag
__blk_mq_tag_busy
-> 1) tag must be idle, which means there can't be inflight IO
spin_lock_irq(&tags->lock) -> lock B (hctx->tags) spin_unlock_irq(&tags->lock) -> unlock B, turn on interrupt accidentally
-> 2) context must be preempt by IO interrupt to trigger deadlock.
As shown above, the deadlock is not possible in theory, but the warning still need to be fixed.
Fix it by using spin_lock_irqsave to get lockB instead of spin_lock_irq.
--- block/blk-mq-tag.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
block/blk-mq-tag.c +3 -2
@@ -40,6 +40,7 @@ static void blk_mq_update_wake_batch(struct blk_mq_tags *tags,void __blk_mq_tag_busy (struct blk_mq_hw_ctx *hctx) {unsigned int users; +unsigned long flags;struct blk_mq_tags *tags = hctx->tags;/*
@@ -58,11 +59,11 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)return ; } -spin_lock_irq (&tags->lock); +spin_lock_irqsave (&tags->lock, flags); users = tags->active_queues +1 ;WRITE_ONCE (tags->active_queues, users);blk_mq_update_wake_batch (tags, users); -spin_unlock_irq (&tags->lock); +spin_unlock_irqrestore (&tags->lock, flags); }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 150/321 drm/msm: Reduce fallout of fence signaling vs reclaim hangs
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Clark <[email protected]>
[ Upstream commit 4bea53b9c7c72fd12a0ceebe88a71723c0a514b8 ]
Until various PM devfreq/QoS and interconnect patches land, we could potentially trigger reclaim from gpu scheduler thread, and under enough memory pressure that could trigger a sort of deadlock. Eventually the wait will timeout and we'll move on to consider other GEM objects. But given that there is still a potential for deadlock/stalling, we should reduce the timeout to contain the damage.
Patchwork: https://patchwork.freedesktop.org/patch/568031/
--- drivers/gpu/drm/msm/msm_gem_shrinker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/msm_gem_shrinker.c +1 -1
@@ -76,7 +76,7 @@ static bool wait_for_idle(struct drm_gem_object *obj) {enum dma_resv_usage usage =dma_resv_usage_rw (true); -return dma_resv_wait_timeout (obj->resv, usage, false,1000 ) >0 ; +return dma_resv_wait_timeout (obj->resv, usage, false,10 ) >0 ; } static bool
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 151/321 memory: tegra: Skip SID programming if SID registers arent set
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashish Mhetre <[email protected]>
[ Upstream commit 0d6c918011ce4764ed277de4726a468b7ffe5fed ]
There are few MC clients where SID security and override register offsets are not specified like "sw_cluster0" in tegra234. Don't program SID override for such clients because it leads to access to invalid addresses.
--- drivers/memory/tegra/tegra186.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/memory/tegra/tegra186.c +3 -0
@@ -74,6 +74,9 @@ static void tegra186_mc_client_sid_override(struct tegra_mc *mc, {u32 value, old; +if (client->regs.sid.security ==0 && client->regs.sid.override ==0 ) +return ; + value =readl (mc->regs + client->regs.sid.security);if ((value &MC_SID_STREAMID_SECURITY_OVERRIDE ) ==0 ) {/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 152/321 powerpc/xics: Check return value of kasprintf in icp_native_map_one_cpu
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kunwu Chan <[email protected]>
[ Upstream commit 45b1ba7e5d1f6881050d558baf9bc74a2ae13930 ]
kasprintf() returns a pointer to dynamically allocated memory which can be NULL upon failure. Ensure the allocation was successful by checking the pointer validity.
--- arch/powerpc/sysdev/xics/icp-native.c | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/sysdev/xics/icp-native.c +2 -0
@@ -236,6 +236,8 @@ static int __init icp_native_map_one_cpu(int hw_id, unsigned long addr, rname =kasprintf (GFP_KERNEL ,"CPU %d [0x%x] Interrupt Presentation" , cpu, hw_id); +if (!rname) +return -ENOMEM ;if (!request_mem_region (addr, size, rname)) {pr_warn ("icp_native: Could not reserve ICP MMIO for CPU %d, interrupt server #0x%x\n" , cpu, hw_id);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 153/321 ASoC: SOF: ipc4: check return value of snd_sof_ipc_msg_data
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bard Liao <[email protected]>
[ Upstream commit 2bd512626f8ea3957c981cadd2ebf75feff737dd ]
snd_sof_ipc_msg_data could return error.
--- sound/soc/sof/ipc4.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
sound/soc/sof/ipc4.c +8 -1
@@ -616,7 +616,14 @@ static void sof_ipc4_rx_msg(struct snd_sof_dev *sdev)return ; ipc4_msg->data_size = data_size; -snd_sof_ipc_msg_data (sdev,NULL , ipc4_msg->data_ptr, ipc4_msg->data_size); + err =snd_sof_ipc_msg_data (sdev,NULL , ipc4_msg->data_ptr, ipc4_msg->data_size); +if (err <0 ) { +dev_err (sdev->dev,"failed to read IPC notification data: %d\n" , err); +kfree (ipc4_msg->data_ptr); + ipc4_msg->data_ptr =NULL ; + ipc4_msg->data_size =0 ; +return ; + } }sof_ipc4_log_header (sdev->dev,"ipc rx done " , ipc4_msg, true);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 154/321 hwmon: (pc87360) Bounds check data->innr usage
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
[ Upstream commit 4265eb062a7303e537ab3792ade31f424c3c5189 ]
Without visibility into the initializers for data->innr, GCC suspects using it as an index could walk off the end of the various 14-element arrays in data. Perform an explicit clamp to the array size. Silences the following warning with GCC 12+:
../drivers/hwmon/pc87360.c: In function 'pc87360_update_device':../drivers/hwmon/pc87360.c:341:49: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
341 | data->in_max[i] = pc87360_read_value(data,
| ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
342 | LD_IN, i,
| ~~~~~~~~~
343 | PC87365_REG_IN_MAX);
| ~~~~~~~~~~~~~~~~~~~
../drivers/hwmon/pc87360.c:209:12: note: at offset 255 into destination object 'in_max' of size 14
209 | u8 in_max[14]; /* Register value */
| ^~~~~~--- drivers/hwmon/pc87360.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/hwmon/pc87360.c +5 -1
@@ -323,7 +323,11 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) }/* Voltages */ -for (i =0 ; i < data->innr; i++) { +/* +* The min() below does not have any practical meaning and is +* only needed to silence a warning observed with gcc 12+. +*/ +for (i =0 ; i <min (data->innr,ARRAY_SIZE (data->in)); i++) { data->in_status[i] =pc87360_read_value (data,LD_IN , i,PC87365_REG_IN_STATUS );/* Clear bits */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 155/321 drm/rockchip: vop2: clear afbc en and transform bit for cluster window at linear mode
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Yan <[email protected]>
[ Upstream commit 20529a68307feed00dd3d431d3fff0572616b0f2 ]
The enable bit and transform offset of cluster windows should be cleared when it work at linear mode, or we may have a iommu fault issue on rk3588 which cluster windows switch between afbc and linear mode.
As the cluster windows of rk3568 only supports afbc format so is therefore not affected.
--- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +5 -0
@@ -1258,6 +1258,11 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,vop2_win_write (win,VOP2_WIN_AFBC_ROTATE_270 , rotate_270);vop2_win_write (win,VOP2_WIN_AFBC_ROTATE_90 , rotate_90); }else { +if (vop2_cluster_window (win)) { +vop2_win_write (win,VOP2_WIN_AFBC_ENABLE ,0 ); +vop2_win_write (win,VOP2_WIN_AFBC_TRANSFORM_OFFSET ,0 ); + } +vop2_win_write (win,VOP2_WIN_YRGB_VIR ,DIV_ROUND_UP (fb->pitches[0 ],4 )); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 156/321 Bluetooth: hci_conn: Check non NULL function before calling for HFP offload
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zijun Hu <[email protected]>
[ Upstream commit 132d0fd0b8418094c9e269e5bc33bf5b864f4a65 ]
For some controllers such as QCA2066, it does not need to send HCI_Configure_Data_Path to configure non-HCI data transport path to support HFP offload, their device drivers may set hdev->get_codec_config_data as NULL, so Explicitly add this non NULL checking before calling the function.
--- net/bluetooth/hci_conn.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
net/bluetooth/hci_conn.c +8 -3
@@ -293,6 +293,13 @@ static int configure_datapath_sync(struct hci_dev *hdev, struct bt_codec *codec)__u8 vnd_len, *vnd_data =NULL ;struct hci_op_configure_data_path *cmd =NULL ; +if (!codec->data_path || !hdev->get_codec_config_data) +return 0 ; + +/* Do not take me as error */ +if (!hdev->get_codec_config_data) +return 0 ; + err = hdev->get_codec_config_data (hdev,ESCO_LINK , codec, &vnd_len, &vnd_data);if (err <0 )
@@ -338,9 +345,7 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)bt_dev_dbg (hdev,"hcon %p" , conn); -/* for offload use case, codec needs to configured before opening SCO */ -if (conn->codec.data_path) -configure_datapath_sync (hdev, &conn->codec); +configure_datapath_sync (hdev, &conn->codec); conn->state =BT_CONNECT ; conn->out = true;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 157/321 gfs2: Refcounting fix in gfs2_thaw_super
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit 4e58543e7da4859c4ba61d15493e3522b6ad71fd ]
It turns out that the .freeze_super and .thaw_super operations require the filesystem to manage the superblock refcount itself. We are using the freeze_super() and thaw_super() helpers to mostly take care of that for us, but this means that the superblock may no longer be around by when thaw_super() returns, and gfs2_thaw_super() will then access freed memory. Take an extra superblock reference in gfs2_thaw_super() to fix that.
--- fs/gfs2/super.c | 2 ++ 1 file changed, 2 insertions(+)
fs/gfs2/super.c +2 -0
@@ -814,6 +814,7 @@ static int gfs2_thaw_super(struct super_block *sb)if (!test_bit (SDF_FREEZE_INITIATOR , &sdp->sd_flags)) goto out; +atomic_inc (&sb->s_active);gfs2_freeze_unlock (&sdp->sd_freeze_gh); error =gfs2_do_thaw (sdp);
@@ -824,6 +825,7 @@ static int gfs2_thaw_super(struct super_block *sb) } out:mutex_unlock (&sdp->sd_freeze_mutex); +deactivate_super (sb);return error; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 158/321 nvmet-trace: avoid dereferencing pointer too early
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Wagner <[email protected]>
[ Upstream commit 0e716cec6fb11a14c220ee17c404b67962e902f7 ]
The first command issued from the host to the target is the fabrics connect command. At this point, neither the target queue nor the controller have been allocated. But we already try to trace this command in nvmet_req_init.
Reported by KASAN.
--- drivers/nvme/target/trace.c | 6 +++--- drivers/nvme/target/trace.h | 28 +++++++++++++++++----------- 2 files changed, 20 insertions(+), 14 deletions(-)
drivers/nvme/target/trace.c +3 -3
@@ -211,7 +211,7 @@ const char *nvmet_trace_disk_name(struct trace_seq *p, char *name)return ret; } -const char *nvmet_trace_ctrl_name (struct trace_seq *p,struct nvmet_ctrl *ctrl) +const char *nvmet_trace_ctrl_id (struct trace_seq *p,u16 ctrl_id) {const char *ret =trace_seq_buffer_ptr (p);
@@ -224,8 +224,8 @@ const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl)* If we can know the extra data of the connect command in this stage, * we can update this print statement later. */ -if (ctrl) -trace_seq_printf (p,"%d" , ctrl->cntlid); +if (ctrl_id) +trace_seq_printf (p,"%d" , ctrl_id);else trace_seq_printf (p,"_" );trace_seq_putc (p,0 );
drivers/nvme/target/trace.h +17 -11
@@ -32,18 +32,24 @@ const char *nvmet_trace_parse_fabrics_cmd(struct trace_seq *p, u8 fctype, nvmet_trace_parse_nvm_cmd(p, opcode, cdw10) : \ nvmet_trace_parse_admin_cmd(p, opcode, cdw10))) -const char *nvmet_trace_ctrl_name (struct trace_seq *p,struct nvmet_ctrl *ctrl); -#define __print_ctrl_name (ctrl) \ - nvmet_trace_ctrl_name(p, ctrl) +const char *nvmet_trace_ctrl_id (struct trace_seq *p,u16 ctrl_id); +#define __print_ctrl_id (ctrl_id) \ + nvmet_trace_ctrl_id(p, ctrl_id)const char *nvmet_trace_disk_name (struct trace_seq *p,char *name);#define __print_disk_name (name) \ nvmet_trace_disk_name(p, name)#ifndef TRACE_HEADER_MULTI_READ -static inline struct nvmet_ctrl *nvmet_req_to_ctrl (struct nvmet_req *req) +static inline u16 nvmet_req_to_ctrl_id (struct nvmet_req *req) { -return req->sq->ctrl; +/* +* The queue and controller pointers are not valid until an association +* has been established. +*/ +if (!req->sq || !req->sq->ctrl) +return 0 ; +return req->sq->ctrl->cntlid; }static inline void __assign_req_name (char *name,struct nvmet_req *req)
@@ -62,7 +68,7 @@ TRACE_EVENT(nvmet_req_init, TP_ARGS(req, cmd),TP_STRUCT__entry (__field (struct nvme_command *,cmd ) - __field(struct nvmet_ctrl *, ctrl) +__field (u16, ctrl_id)__array (char, disk,DISK_NAME_LEN )__field (int, qid) __field(u16, cid)
@@ -75,7 +81,7 @@ TRACE_EVENT(nvmet_req_init, ), TP_fast_assign( __entry->cmd = cmd; - __entry->ctrl =nvmet_req_to_ctrl (req); + __entry->ctrl_id =nvmet_req_to_ctrl_id (req);__assign_req_name (__entry->disk, req); __entry->qid = req->sq->qid; __entry->cid = cmd->common.command_id;
@@ -89,7 +95,7 @@ TRACE_EVENT(nvmet_req_init, ), TP_printk("nvmet%s: %sqid=%d, cmdid=%u, nsid=%u, flags=%#x, " "meta=%#llx, cmd=(%s, %s)", - __print_ctrl_name(__entry->ctrl), + __print_ctrl_id(__entry->ctrl_id), __print_disk_name(__entry->disk), __entry->qid, __entry->cid, __entry->nsid, __entry->flags, __entry->metadata,
@@ -103,7 +109,7 @@ TRACE_EVENT(nvmet_req_complete, TP_PROTO(struct nvmet_req *req), TP_ARGS(req), TP_STRUCT__entry( - __field(struct nvmet_ctrl *, ctrl) + __field(u16, ctrl_id) __array(char, disk, DISK_NAME_LEN) __field(int, qid) __field(int, cid)
@@ -111,7 +117,7 @@ TRACE_EVENT(nvmet_req_complete,__field (u16, status) ),TP_fast_assign ( - __entry->ctrl = nvmet_req_to_ctrl(req); + __entry->ctrl_id = nvmet_req_to_ctrl_id(req); __entry->qid = req->cq->qid; __entry->cid = req->cqe->command_id; __entry->result =le64_to_cpu (req->cqe->result.u64);
@@ -119,7 +125,7 @@ TRACE_EVENT(nvmet_req_complete,__assign_req_name (__entry->disk, req); ),TP_printk ("nvmet%s: %sqid=%d, cmdid=%u, res=%#llx, status=%#x" , -__print_ctrl_name (__entry->ctrl), +__print_ctrl_id (__entry->ctrl_id),__print_disk_name (__entry->disk), __entry->qid, __entry->cid, __entry->result, __entry->status)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 159/321 ext4: do not trim the group with corrupted block bitmap
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 172202152a125955367393956acf5f4ffd092e0d ]
Otherwise operating on an incorrupted block bitmap can lead to all sorts of unknown problems.
--- fs/ext4/mballoc.c | 3 +++ 1 file changed, 3 insertions(+)
fs/ext4/mballoc.c +3 -0
@@ -6483,6 +6483,9 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))bool set_trimmed = false;void *bitmap; +if (unlikely (EXT4_MB_GRP_BBITMAP_CORRUPT (e4b->bd_info))) +return 0 ; + last =ext4_last_grp_cluster (sb, e4b->bd_group); bitmap = e4b->bd_bitmap;if (start ==0 && max >= last)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 160/321 afs: fix __afs_break_callback() / afs_drop_open_mmap() race
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 275655d3207b9e65d1561bf21c06a622d9ec1d43 ]
In __afs_break_callback() we might check ->cb_nr_mmap and if it's non-zero do queue_work(&vnode->cb_work). In afs_drop_open_mmap() we decrement ->cb_nr_mmap and do flush_work(&vnode->cb_work) if it reaches zero.
The trouble is, there's nothing to prevent __afs_break_callback() from seeing ->cb_nr_mmap before the decrement and do queue_work() after both the decrement and flush_work(). If that happens, we might be in trouble - vnode might get freed before the queued work runs.
__afs_break_callback() is always done under ->cb_lock, so let's make sure that ->cb_nr_mmap can change from non-zero to zero while holding ->cb_lock (the spinlock component of it - it's a seqlock and we don't need to mess with the counter).
--- fs/afs/file.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
fs/afs/file.c +6 -2
@@ -525,13 +525,17 @@ static void afs_add_open_mmap(struct afs_vnode *vnode)static void afs_drop_open_mmap (struct afs_vnode *vnode) { -if (!atomic_dec_and_test (&vnode->cb_nr_mmap)) +if (atomic_add_unless (&vnode->cb_nr_mmap,-1 ,1 ))return ;down_write (&vnode->volume->cell->fs_open_mmaps_lock); -if (atomic_read (&vnode->cb_nr_mmap) ==0 ) +read_seqlock_excl (&vnode->cb_lock); +// the only place where ->cb_nr_mmap may hit 0 +// see __afs_break_callback() for the other side... +if (atomic_dec_and_test (&vnode->cb_nr_mmap))list_del_init (&vnode->cb_mmap_link); +read_sequnlock_excl (&vnode->cb_lock);up_write (&vnode->volume->cell->fs_open_mmaps_lock);flush_work (&vnode->cb_work);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 161/321 fuse: fix UAF in rcu pathwalks
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 053fc4f755ad43cf35210677bcba798ccdc48d0c ]
->permission(), ->get_link() and ->inode_get_acl() might dereference ->s_fs_info (and, in case of ->permission(), ->s_fs_info->fc->user_ns as well) when called from rcu pathwalk.
Freeing ->s_fs_info->fc is rcu-delayed; we need to make freeing ->s_fs_info and dropping ->user_ns rcu-delayed too.
--- fs/fuse/cuse.c | 3 +-- fs/fuse/fuse_i.h | 1 + fs/fuse/inode.c | 15 +++++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-)
fs/fuse/cuse.c +1 -2
@@ -474,8 +474,7 @@ static int cuse_send_init(struct cuse_conn *cc)static void cuse_fc_release (struct fuse_conn *fc) { -struct cuse_conn *cc =fc_to_cc (fc); -kfree_rcu (cc, fc.rcu); +kfree (fc_to_cc (fc)); }/**
fs/fuse/fuse_i.h +1 -0
@@ -872,6 +872,7 @@ struct fuse_mount {/* Entry on fc->mounts */ struct list_head fc_entry; +struct rcu_head rcu; };static inline struct fuse_mount *get_fuse_mount_super (struct super_block *sb)
fs/fuse/inode.c +11 -4
@@ -925,6 +925,14 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, }EXPORT_SYMBOL_GPL (fuse_conn_init); +static void delayed_release (struct rcu_head *p) +{ + struct fuse_conn *fc = container_of(p, struct fuse_conn, rcu); + +put_user_ns (fc->user_ns); + fc->release (fc); +} +void fuse_conn_put (struct fuse_conn *fc) {if (refcount_dec_and_test (&fc->count)) {
@@ -936,13 +944,12 @@ void fuse_conn_put(struct fuse_conn *fc)if (fiq->ops->release) fiq->ops->release (fiq);put_pid_ns (fc->pid_ns); -put_user_ns (fc->user_ns); bucket =rcu_dereference_protected (fc->curr_bucket,1 );if (bucket) {WARN_ON (atomic_read (&bucket->count) !=1 );kfree (bucket); } - fc->release (fc); +call_rcu (&fc->rcu, delayed_release); } }EXPORT_SYMBOL_GPL (fuse_conn_put);
@@ -1356,7 +1363,7 @@ EXPORT_SYMBOL_GPL(fuse_send_init);void fuse_free_conn (struct fuse_conn *fc) {WARN_ON (!list_empty (&fc->devices)); -kfree_rcu (fc, rcu); +kfree (fc); }EXPORT_SYMBOL_GPL (fuse_free_conn);
@@ -1895,7 +1902,7 @@ static void fuse_sb_destroy(struct super_block *sb)void fuse_mount_destroy (struct fuse_mount *fm) {fuse_conn_put (fm->fc); -kfree (fm); +kfree_rcu (fm, rcu); }EXPORT_SYMBOL (fuse_mount_destroy);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 162/321 quota: Remove BUG_ON from dqget()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit 249f374eb9b6b969c64212dd860cc1439674c4a8 ]
dqget() checks whether dquot->dq_sb is set when returning it using BUG_ON. Firstly this doesn't work as an invalidation check for quite some time (we release dquot with dq_sb set these days), secondly using BUG_ON is quite harsh. Use WARN_ON_ONCE and check whether dquot is still hashed instead.
--- fs/quota/dquot.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
fs/quota/dquot.c +2 -3
@@ -995,9 +995,8 @@ struct dquot *dqget(struct super_block *sb, struct kqid qid)* smp_mb__before_atomic() in dquot_acquire(). */ smp_rmb (); -#ifdef CONFIG_QUOTA_DEBUG -BUG_ON (!dquot->dq_sb);/* Has somebody invalidated entry under us? */ -#endif +/* Has somebody invalidated entry under us? */ +WARN_ON_ONCE (hlist_unhashed (&dquot->dq_hash)); out:if (empty)do_destroy_dquot (empty);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 163/321 kernfs: fix false-positive WARN(nr_mmapped) in kernfs_drain_open_files
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Neel Natu <[email protected]>
[ Upstream commit 05d8f255867e3196565bb31a911a437697fab094 ]
Prior to this change 'on->nr_mmapped' tracked the total number of mmaps across all of its associated open files via kernfs_fop_mmap(). Thus if the file descriptor associated with a kernfs_open_file was mmapped 10 times then we would have: 'of->mmapped = true' and 'of_on(of)->nr_mmapped = 10'.
The problem is that closing or draining a 'of->mmapped' file would only decrement one from the 'of_on(of)->nr_mmapped' counter.
For e.g. we have this from kernfs_unlink_open_file():
if (of->mmapped)
on->nr_mmapped--;The WARN_ON_ONCE(on->nr_mmapped) in kernfs_drain_open_files() is easy to reproduce by:
1. opening a (mmap-able) kernfs file.
2. mmap-ing that file more than once (mapping just once masks the issue).
3. trigger a drain of that kernfs file.
Modulo out-of-tree patches I was able to trigger this reliably by identifying pci device nodes in sysfs that have resource regions that are mmap-able and that don't have any driver attached to them (steps 1 and 2). For step 3 we can "echo 1 > remove" to trigger a kernfs_drain.
--- fs/kernfs/file.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/kernfs/file.c +5 -3
@@ -532,9 +532,11 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma) goto out_put; rc =0 ; - of->mmapped = true; -of_on (of)->nr_mmapped++; - of->vm_ops = vma->vm_ops; +if (!of->mmapped) { + of->mmapped = true; +of_on (of)->nr_mmapped++; + of->vm_ops = vma->vm_ops; + } vma->vm_ops = &kernfs_vm_ops; out_put:kernfs_put_active (of->kn);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 164/321 media: pci: cx23885: check cx23885_vdev_init() return
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil <[email protected]>
[ Upstream commit 15126b916e39b0cb67026b0af3c014bfeb1f76b3 ]
cx23885_vdev_init() can return a NULL pointer, but that pointer is used in the next line without a check.
Add a NULL pointer check and go to the error unwind if it is NULL.
--- drivers/media/pci/cx23885/cx23885-video.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/media/pci/cx23885/cx23885-video.c +8 -0
@@ -1354,6 +1354,10 @@ int cx23885_video_register(struct cx23885_dev *dev)/* register Video device */ dev->video_dev =cx23885_vdev_init (dev, dev->pci, &cx23885_video_template,"video" ); +if (!dev->video_dev) { + err = -ENOMEM ; + goto fail_unreg; + } dev->video_dev->queue = &dev->vb2_vidq; dev->video_dev->device_caps =V4L2_CAP_READWRITE |V4L2_CAP_STREAMING |V4L2_CAP_AUDIO |V4L2_CAP_VIDEO_CAPTURE ;
@@ -1382,6 +1386,10 @@ int cx23885_video_register(struct cx23885_dev *dev)/* register VBI device */ dev->vbi_dev =cx23885_vdev_init (dev, dev->pci, &cx23885_vbi_template,"vbi" ); +if (!dev->vbi_dev) { + err = -ENOMEM ; + goto fail_unreg; + } dev->vbi_dev->queue = &dev->vb2_vbiq; dev->vbi_dev->device_caps =V4L2_CAP_READWRITE |V4L2_CAP_STREAMING |V4L2_CAP_AUDIO |V4L2_CAP_VBI_CAPTURE ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 165/321 fs: binfmt_elf_efpic: dont use missing interpreters properties
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Max Filippov <[email protected]>
[ Upstream commit 15fd1dc3dadb4268207fa6797e753541aca09a2a ]
Static FDPIC executable may get an executable stack even when it has non-executable GNU_STACK segment. This happens when STACK segment has rw permissions, but does not specify stack size. In that case FDPIC loader uses permissions of the interpreter's stack, and for static executables with no interpreter it results in choosing the arch-default permissions for the stack.
Fix that by using the interpreter's properties only when the interpreter is actually used.
--- fs/binfmt_elf_fdpic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/binfmt_elf_fdpic.c +1 -1
@@ -320,7 +320,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)else executable_stack =EXSTACK_DEFAULT ; -if (stack_size ==0 ) { +if (stack_size ==0 && interp_params.flags &ELF_FDPIC_FLAG_PRESENT ) { stack_size = interp_params.stack_size;if (interp_params.flags &ELF_FDPIC_FLAG_EXEC_STACK ) executable_stack =EXSTACK_ENABLE_X ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 166/321 scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Tee <[email protected]>
[ Upstream commit 3d0f9342ae200aa1ddc4d6e7a573c6f8f068d994 ]
A static code analyzer tool indicates that the local variable called status in the lpfc_sli4_repost_sgl_list() routine could be used to print garbage uninitialized values in the routine's log message.
Fix by initializing to zero.
--- drivers/scsi/lpfc/lpfc_sli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/lpfc/lpfc_sli.c +1 -1
@@ -7596,7 +7596,7 @@ lpfc_sli4_repost_sgl_list(struct lpfc_hba *phba,struct lpfc_sglq *sglq_entry =NULL ;struct lpfc_sglq *sglq_entry_next =NULL ;struct lpfc_sglq *sglq_entry_first =NULL ; -int status, total_cnt; +int status =0 , total_cnt;int post_cnt =0 , num_posted =0 , block_cnt =0 ;int last_xritag =NO_XRI ;LIST_HEAD (prep_sgl_list);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 167/321 media: drivers/media/dvb-core: copy user arrays safely
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philipp Stanner <[email protected]>
[ Upstream commit 102fb77c2deb0df3683ef8ff7a6f4cf91dc456e2 ]
At several positions in dvb_frontend.c, memdup_user() is utilized to copy userspace arrays. This is done without overflow checks.
Use the new wrapper memdup_array_user() to copy the arrays more safely.
--- drivers/media/dvb-core/dvb_frontend.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/media/dvb-core/dvb_frontend.c +8 -4
@@ -2160,7 +2160,8 @@ static int dvb_frontend_handle_compat_ioctl(struct file *file, unsigned int cmd,if (!tvps->num || (tvps->num >DTV_IOCTL_MAX_MSGS ))return -EINVAL ; - tvp =memdup_user (compat_ptr (tvps->props), tvps->num *sizeof (*tvp)); + tvp =memdup_array_user (compat_ptr (tvps->props), + tvps->num,sizeof (*tvp));if (IS_ERR (tvp))return PTR_ERR (tvp);
@@ -2191,7 +2192,8 @@ static int dvb_frontend_handle_compat_ioctl(struct file *file, unsigned int cmd,if (!tvps->num || (tvps->num >DTV_IOCTL_MAX_MSGS ))return -EINVAL ; - tvp =memdup_user (compat_ptr (tvps->props), tvps->num *sizeof (*tvp)); + tvp =memdup_array_user (compat_ptr (tvps->props), + tvps->num,sizeof (*tvp));if (IS_ERR (tvp))return PTR_ERR (tvp);
@@ -2368,7 +2370,8 @@ static int dvb_get_property(struct dvb_frontend *fe, struct file *file,if (!tvps->num || tvps->num >DTV_IOCTL_MAX_MSGS )return -EINVAL ; - tvp =memdup_user ((void __user *)tvps->props, tvps->num *sizeof (*tvp)); + tvp =memdup_array_user ((void __user *)tvps->props, + tvps->num,sizeof (*tvp));if (IS_ERR (tvp))return PTR_ERR (tvp);
@@ -2446,7 +2449,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,if (!tvps->num || (tvps->num >DTV_IOCTL_MAX_MSGS ))return -EINVAL ; - tvp =memdup_user ((void __user *)tvps->props, tvps->num *sizeof (*tvp)); + tvp =memdup_array_user ((void __user *)tvps->props, + tvps->num,sizeof (*tvp));if (IS_ERR (tvp))return PTR_ERR (tvp);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 168/321 net/sun3_82586: Avoid reading past buffer in debug output
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
[ Upstream commit 4bea747f3fbec33c16d369b2f51e55981d7c78d0 ]
Since NUM_XMIT_BUFFS is always 1, building m68k with sun3_defconfig and -Warraybounds, this build warning is visible[1]:
drivers/net/ethernet/i825xx/sun3_82586.c: In function 'sun3_82586_timeout':drivers/net/ethernet/i825xx/sun3_82586.c:990:122: warning: array subscript 1 is above array bounds of 'volatile struct transmit_cmd_struct *[1]' [-Warray-bounds=]
990 | printk("%s: command-stats: %04x %04x\n",dev->name,swab16(p->xmit_cmds[0]->cmd_status),swab16(p->xmit_cmds[1]->cmd_status));
| ~~~~~~~~~~~~^~~
...drivers/net/ethernet/i825xx/sun3_82586.c:156:46: note: while referencing 'xmit_cmds'
156 | volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
Avoid accessing index 1 since it doesn't exist.
--- drivers/net/ethernet/i825xx/sun3_82586.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/i825xx/sun3_82586.c +1 -1
@@ -986,7 +986,7 @@ static void sun3_82586_timeout(struct net_device *dev, unsigned int txqueue) {#ifdef DEBUG printk ("%s: xmitter timed out, try to restart! stat: %02x\n" ,dev->name,p->scb->cus); -printk ("%s: command-stats: %04x %04x\n" ,dev->name,swab16 (p->xmit_cmds[0 ]->cmd_status),swab16 (p->xmit_cmds[1 ]->cmd_status)); +printk ("%s: command-stats: %04x\n" , dev->name,swab16 (p->xmit_cmds[0 ]->cmd_status));printk ("%s: check, whether you set the right interrupt number!\n" ,dev->name);#endif sun3_82586_close (dev);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 169/321 drm/lima: set gp bus_stop bit before hard reset
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Erico Nunes <[email protected]>
[ Upstream commit 27aa58ec85f973d98d336df7b7941149308db80f ]
This is required for reliable hard resets. Otherwise, doing a hard reset while a task is still running (such as a task which is being stopped by the drm_sched timeout handler) may result in random mmu write timeouts or lockups which cause the entire gpu to hang.
--- drivers/gpu/drm/lima/lima_gp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/gpu/drm/lima/lima_gp.c +12 -0
@@ -166,6 +166,11 @@ static void lima_gp_task_run(struct lima_sched_pipe *pipe,gp_write (LIMA_GP_CMD , cmd); } +static int lima_gp_bus_stop_poll (struct lima_ip *ip) +{ +return !!(gp_read (LIMA_GP_STATUS ) &LIMA_GP_STATUS_BUS_STOPPED ); +} +static int lima_gp_hard_reset_poll (struct lima_ip *ip) {gp_write (LIMA_GP_PERF_CNT_0_LIMIT ,0xC01A0000 );
@@ -179,6 +184,13 @@ static int lima_gp_hard_reset(struct lima_ip *ip)gp_write (LIMA_GP_PERF_CNT_0_LIMIT ,0xC0FFE000 );gp_write (LIMA_GP_INT_MASK ,0 ); + +gp_write (LIMA_GP_CMD ,LIMA_GP_CMD_STOP_BUS ); + ret =lima_poll_timeout (ip, lima_gp_bus_stop_poll,10 ,100 ); +if (ret) { +dev_err (dev->dev,"%s bus stop timeout\n" ,lima_ip_name (ip)); +return ret; + }gp_write (LIMA_GP_CMD ,LIMA_GP_CMD_RESET ); ret =lima_poll_timeout (ip, lima_gp_hard_reset_poll,10 ,100 );if (ret) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 170/321 hrtimer: Select housekeeping CPU during migration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Costa Shulyupin <[email protected]>
[ Upstream commit 56c2cb10120894be40c40a9bf0ce798da14c50f6 ]
During CPU-down hotplug, hrtimers may migrate to isolated CPUs, compromising CPU isolation.
Address this issue by masking valid CPUs for hrtimers using housekeeping_cpumask(HK_TYPE_TIMER).
--- kernel/time/hrtimer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/time/hrtimer.c +2 -1
@@ -38,6 +38,7 @@#include <linux/sched/deadline.h> #include <linux/sched/nohz.h> #include <linux/sched/debug.h> +#include <linux/sched/isolation.h> #include <linux/timer.h> #include <linux/freezer.h> #include <linux/compat.h>
@@ -2220,8 +2221,8 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,int hrtimers_cpu_dying (unsigned int dying_cpu) { +int i, ncpu =cpumask_any_and (cpu_active_mask,housekeeping_cpumask (HK_TYPE_TIMER ));struct hrtimer_cpu_base *old_base, *new_base; -int i, ncpu =cpumask_first (cpu_active_mask);tick_cancel_sched_timer (dying_cpu);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 171/321 virtiofs: forbid newlines in tags
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Hajnoczi <[email protected]>
[ Upstream commit 40488cc16f7ea0d193a4e248f0d809c25cc377db ]
Newlines in virtiofs tags are awkward for users and potential vectors for string injection attacks.
--- fs/fuse/virtio_fs.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/fuse/virtio_fs.c +10 -0
@@ -323,6 +323,16 @@ static int virtio_fs_read_tag(struct virtio_device *vdev, struct virtio_fs *fs)return -ENOMEM ;memcpy (fs->tag, tag_buf, len); fs->tag[len] ='\0' ; + +/* While the VIRTIO specification allows any character, newlines are +* awkward on mount(8) command-lines and cause problems in the sysfs +* "tag" attr and uevent TAG= properties. Forbid them. +*/ +if (strchr (fs->tag,'\n' )) { +dev_dbg (&vdev->dev,"refusing virtiofs tag with newline character\n" ); +return -EINVAL ; + } +return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 172/321 clocksource/drivers/arm_global_timer: Guard against division by zero
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Blumenstingl <[email protected]>
[ Upstream commit e651f2fae33634175fae956d896277cf916f5d09 ]
The result of the division of new_rate by gt_target_rate can be zero (if new_rate is smaller than gt_target_rate). Using that result as divisor without checking can result in a division by zero error. Guard against this by checking for a zero value earlier.
While here, also change the psv variable to an unsigned long to make sure we don't overflow the datatype as all other types involved are also unsiged long.
--- drivers/clocksource/arm_global_timer.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/clocksource/arm_global_timer.c +5 -6
@@ -290,18 +290,17 @@ static int gt_clk_rate_change_cb(struct notifier_block *nb,switch (event) {case PRE_RATE_CHANGE : { -int psv; +unsigned long psv; - psv =DIV_ROUND_CLOSEST (ndata->new_rate, - gt_target_rate); - -if (abs (gt_target_rate - (ndata->new_rate / psv)) >MAX_F_ERR ) + psv =DIV_ROUND_CLOSEST (ndata->new_rate, gt_target_rate); +if (!psv || +abs (gt_target_rate - (ndata->new_rate / psv)) >MAX_F_ERR )return NOTIFY_BAD ; psv--;/* prescaler within legal range? */ -if (psv <0 || psv >GT_CONTROL_PRESCALER_MAX ) +if (psv >GT_CONTROL_PRESCALER_MAX )return NOTIFY_BAD ;/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 173/321 netlink: hold nlk->cb_mutex longer in __netlink_dump_start()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit b5590270068c4324dac4a2b5a4a156e02e21339f ]
__netlink_dump_start() releases nlk->cb_mutex right before calling netlink_dump() which grabs it again.
This seems dangerous, even if KASAN did not bother yet.
Add a @lock_taken parameter to netlink_dump() to let it grab the mutex if called from netlink_recvmsg() only.
--- net/netlink/af_netlink.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
net/netlink/af_netlink.c +6 -7
@@ -130,7 +130,7 @@ static const char *const nlk_cb_mutex_key_strings[MAX_LINKS + 1] = { "nlk_cb_mutex-MAX_LINKS" }; -static int netlink_dump (struct sock *sk); +static int netlink_dump (struct sock *sk,bool lock_taken);/* nl_table locking explained: * Lookup and traversal are protected with an RCU read-side lock. Insertion
@@ -1953,7 +1953,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,if (READ_ONCE (nlk->cb_running) &&atomic_read (&sk->sk_rmem_alloc) <= sk->sk_rcvbuf /2 ) { - ret =netlink_dump (sk); + ret =netlink_dump (sk, false);if (ret) {WRITE_ONCE (sk->sk_err, -ret);sk_error_report (sk);
@@ -2163,7 +2163,7 @@ static int netlink_dump_done(struct netlink_sock *nlk, struct sk_buff *skb,return 0 ; } -static int netlink_dump (struct sock *sk) +static int netlink_dump (struct sock *sk,bool lock_taken) {struct netlink_sock *nlk =nlk_sk (sk);struct netlink_ext_ack extack = {};
@@ -2175,7 +2175,8 @@ static int netlink_dump(struct sock *sk)int alloc_min_size;int alloc_size; -mutex_lock (nlk->cb_mutex); +if (!lock_taken) +mutex_lock (nlk->cb_mutex);if (!nlk->cb_running) { err = -EINVAL ; goto errout_skb;
@@ -2330,9 +2331,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,WRITE_ONCE (nlk->cb_running, true); nlk->dump_done_errno =INT_MAX ; -mutex_unlock (nlk->cb_mutex); - - ret =netlink_dump (sk); + ret =netlink_dump (sk, true);sock_put (sk);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 174/321 md: clean up invalid BUG_ON in md_ioctl
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Nan <[email protected]>
[ Upstream commit 9dd8702e7cd28ebf076ff838933f29cf671165ec ]
'disk->private_data' is set to mddev in md_alloc() and never set to NULL, and users need to open mddev before submitting ioctl. So mddev must not have been freed during ioctl, and there is no need to check mddev here. Clean up it.
--- drivers/md/md.c | 5 ----- 1 file changed, 5 deletions(-)
drivers/md/md.c +0 -5
@@ -7614,11 +7614,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, mddev = bdev->bd_disk->private_data; -if (!mddev) { -BUG (); - goto out; - } -/* Some actions do not requires the mutex */ switch (cmd) {case GET_ARRAY_INFO :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 175/321 x86: Increase brk randomness entropy for 64-bit systems
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
[ Upstream commit 44c76825d6eefee9eb7ce06c38e1a6632ac7eb7d ]
In commit c1d171a00294 ("x86: randomize brk"), arch_randomize_brk() was defined to use a 32MB range (13 bits of entropy), but was never increased when moving to 64-bit. The default arch_randomize_brk() uses 32MB for 32-bit tasks, and 1GB (18 bits of entropy) for 64-bit tasks.
Update x86_64 to match the entropy used by arm64 and other 64-bit architectures.
--- arch/x86/kernel/process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/x86/kernel/process.c +4 -1
@@ -991,7 +991,10 @@ unsigned long arch_align_stack(unsigned long sp)unsigned long arch_randomize_brk (struct mm_struct *mm) { -return randomize_page (mm->brk,0x02000000 ); +if (mmap_is_ia32 ()) +return randomize_page (mm->brk,SZ_32M ); + +return randomize_page (mm->brk,SZ_1G ); }/*
Signature · 1 line
2.43.0
Re: [PATCH 6.1 175/321] x86: Increase brk randomness entropy for 64-bit systems
Hi all,
this patch introduces a regression in some versions of qemu-aarch64 (at least as built by debian):
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1087822
It doesn't look like it still is a problem with newer versions of qemu so I'm not sure if this should be reverted on master, but it took me a bit of time to track this down to this commit as my reproducer isn't great, so it might make sense to revert this commit on stable branches?
(I don't remember the policies on "don't break userspace", but qemu-user is a bit of a special case here so I'll leave that up to Greg)
I've confirmed that this bug occurs on top of the latest v6.1.118 and goes away reverting this.
(I've also checked the problem also occurs on master and reverting the patch also works around the issue there at this point)
Thank you,
Dominique.
[leaving subject below for context, no more text after this] Greg Kroah-Hartman wrote on Tue, Aug 27, 2024 at 04:38:03PM +0200:
Quoted 19 lines
From: Kees Cook <[email protected]>
[ Upstream commit
44c76825d6eefee9eb7ce06c38e1a6632ac7eb7d]In commit
c1d171a00294("x86: randomize brk"),arch_randomize_brk()was defined to use a 32MB range (13 bits of entropy), but was never increased when moving to 64-bit. The defaultarch_randomize_brk()uses 32MB for 32-bit tasks, and 1GB (18 bits of entropy) for 64-bit tasks.Update
x86_64to match the entropy used by arm64 and other 64-bit architectures.Reported-by [email protected]Signed-off-by Kees Cook <[email protected]>Signed-off-by Thomas Gleixner <[email protected]>Acked-by Jiri Kosina <[email protected]>Closes https://lore.kernel.org/linux-hardening/CA+2EKTVLvc8hDZc+2Yhwmus=dzOUG5E4gV7ayCbu0MPJTZzWkw@mail.gmail.com/ open hereSigned-off-by Sasha Levin <[email protected]>
Signature · 1 line
Dominique Martinet
Re: [PATCH 6.1 175/321] x86: Increase brk randomness entropy for 64-bit systems
Hi,
Quoted 11 lines · Dominique Martinet
Hi all,
this patch introduces a regression in some versions of qemu-aarch64 (at least as built by debian):
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1087822It doesn't look like it still is a problem with newer versions of qemu so I'm not sure if this should be reverted on master, but it took me a bit of time to track this down to this commit as my reproducer isn't great, so it might make sense to revert this commit on stable branches?
Quoted 8 lines
(I don't remember the policies on "don't break userspace", but qemu-user is a bit of a special case here so I'll leave that up to Greg)
I've confirmed that this bug occurs on top of the latest v6.1.118 and goes away reverting this.
(I've also checked the problem also occurs on master and reverting the patch also works around the issue there at this point)
Interestigly there is another report in Debian which identifies the backport of upstream commit 44c76825d6eefee9eb7ce06c38e1a6632ac7eb7d to cause issues in the 6.1.y series:
https://bugs.debian.org/1085762
https://lore.kernel.org/regressions/[email protected]/T/#u
Regards,
Salvatore
Re: [PATCH 6.1 175/321] x86: Increase brk randomness entropy for 64-bit systems
Salvatore Bonaccorso wrote on Wed, Nov 20, 2024 at 08:01:23AM +0100:
Quoted 6 lines
Interestigly there is another report in Debian which identifies the backport of upstream commit
44c76825d6eefee9eb7ce06c38e1a6632ac7eb7dto cause issues in the 6.1.y series:https://bugs.debian.org/1085762
https://lore.kernel.org/regressions/[email protected]/T/#u
Thanks for the heads up!
This would appear to be the same bug (running qemu-aarch64 in user mode on an x86 machine) ?
I've added Ulrich in recipients to confirm he's using qemu-user-static like I was.
Shame I didn't notice all his work, that would have saved me some time :)
Thanks,
Signature · 1 line
Dominique Martinet | Asmadeus
AW: Re: [PATCH 6.1 175/321] x86: Increase brk randomness entropy for 64-bit systems
Hi Dominique & all,
Quoted 8 lines
Salvatore Bonaccorso wrote on Wed, Nov 20, 2024 at 08:01:23AM +0100:
Quoted 6 lines
Interestigly there is another report in Debian which identifies the backport of upstream commit
44c76825d6eefee9eb7ce06c38e1a6632ac7eb7dto cause issues in the 6.1.y series:https://bugs.debian.org/1085762
https://lore.kernel.org/regressions/[email protected]/T/#u
Quoted 6 lines
Thanks for the heads up!
This would appear to be the same bug (running qemu-aarch64 in user mode on an x86 machine) ?
I've added Ulrich in recipients to confirm he's using qemu-user-static like I was.
pbuilder uses qemu inside the ARM64 chroot, yes. I don't know which variety of qemu, though.
Quoted 2 lines
Shame I didn't notice all his work, that would have saved me some time :)
Well, at least we now have confirmation from two different git bisects done by two different developers, pointing to the same commit ;-)
HTH,
Uli
Mit freundlichen Grüßen / Kind regards
Dipl.-Inform. Ulrich Teichert
Senior Software Developer
e.bs kumkeo GmbH
Heidenkampsweg 82a
20097 Hamburg
Germany
T: +49 40 2846761-0
F: +49 40 2846761-99
[email protected]
www.kumkeo.de
Amtsgericht Hamburg / Hamburg District Court, HRB 187712 Geschäftsführer / Managing Director: Michael Leitner; Günter Hagspiel
Re: Re: [PATCH 6.1 175/321] x86: Increase brk randomness entropy for 64-bit systems
Quoted 17 lines · Ulrich Teichert
Hi Dominique & all,
Quoted 8 lines
Salvatore Bonaccorso wrote on Wed, Nov 20, 2024 at 08:01:23AM +0100:
Quoted 6 lines
Interestigly there is another report in Debian which identifies the backport of upstream commit
44c76825d6eefee9eb7ce06c38e1a6632ac7eb7dto cause issues in the 6.1.y series:https://bugs.debian.org/1085762
https://lore.kernel.org/regressions/[email protected]/T/#uQuoted 6 lines
Thanks for the heads up!
This would appear to be the same bug (running qemu-aarch64 in user mode on an x86 machine) ?
I've added Ulrich in recipients to confirm he's using qemu-user-static like I was.
Quoted 7 lines
pbuilder uses qemu inside the ARM64 chroot, yes. I don't know which variety of qemu, though.
Quoted 2 lines
Shame I didn't notice all his work, that would have saved me some time :)
Well, at least we now have confirmation from two different git bisects done by two different developers, pointing to the same commit ;-)
It seems like the correct first step is to revert the brk change. It's still not clear to me why the change is causing a problem -- I assume it is colliding with some other program area.
Is the problem strictly with qemu-user-static? (i.e. it was GCC running in qemu-user-static so the crash is qemu, not GCC) That should help me narrow down the issue. There must be some built-in assumption. And it's aarch64 within x86_64 where it happens (is the program within qemu also aarch64 or is it arm32)?
Is there an simple reproducer?
-Kees
Signature · 1 line
Kees Cook
Re: Re: [PATCH 6.1 175/321] x86: Increase brk randomness entropy for 64-bit systems
Quoted 26 lines · Kees Cook
Quoted 14 lines
Quoted 7 lines
Quoted 6 lines
Interestigly there is another report in Debian which identifies the backport of upstream commit
44c76825d6eefee9eb7ce06c38e1a6632ac7eb7dto cause issues in the 6.1.y series:https://bugs.debian.org/1085762
https://lore.kernel.org/regressions/[email protected]/T/#uQuoted 6 lines
Thanks for the heads up!
This would appear to be the same bug (running qemu-aarch64 in user mode on an x86 machine) ?
I've added Ulrich in recipients to confirm he's using qemu-user-static like I was.Quoted 7 lines
pbuilder uses qemu inside the ARM64 chroot, yes. I don't know which variety of qemu, though.
Quoted 2 lines
Shame I didn't notice all his work, that would have saved me some time :)
Well, at least we now have confirmation from two different git bisects done by two different developers, pointing to the same commit ;-)
It seems like the correct first step is to revert the brk change. It's still not clear to me why the change is causing a problem -- I assume it is colliding with some other program area.
Quoted 7 lines
Is the problem strictly with qemu-user-static? (i.e. it was GCC running in qemu-user-static so the crash is qemu, not GCC) That should help me narrow down the issue. There must be some built-in assumption. And it's aarch64 within
x86_64where it happens (is the program within qemu also aarch64 or is it arm32)?Is there an simple reproducer?
Also seeing /proc/<pid>/maps from a working case (without the patch) might give some clue.
Thanks,
Signature · 2 lines
Jiri Kosina SUSE Labs
Re: Re: [PATCH 6.1 175/321] x86: Increase brk randomness entropy for 64-bit systems
In reply to Kees CookThank you for the replies,
Kees Cook wrote on Wed, Nov 20, 2024 at 10:08:04AM -0800:
Quoted 9 lines
It seems like the correct first step is to revert the brk change. It's still not clear to me why the change is causing a problem -- I assume it is colliding with some other program area.
Is the problem strictly with qemu-user-static? (i.e. it was GCC running in qemu-user-static so the crash is qemu, not GCC) That should help me narrow down the issue. There must be some built-in assumption. And it's aarch64 within
x86_64where it happens (is the program within qemu also aarch64 or is it arm32)?
As far as I'm aware I've only seen qemu-user-static fail for aarch64 (e.g. the arm32 variant works fine, didn't try other arches) in this particular configuration (the debian bookworm package has been built with --static-pie which is known to cause problems)
It's also fixed in newer versions of qemu, even with --static-pie, because they reworked the way they detect program mapppins in qemu commit dd55885516 ("linux-user: Rewrite non-fixed probe_guest_base") and that also fixed the issue (in qemu 8.1.0)
So, in short there are many fixes available; it's a qemu bug that assumed something about the memory layout and broke with this kaslr patch (and for some reason only happened on non-pie static build)
mjt will at the very least rebuild the package with pie enabled, because it's known to cause other issues with aarch64 and that was an oversight in the first place, so this issue will go away for debian without any further work.
This is the background behind me saying that this probably should be reverted in stable branches (to avoid other surprises with old userspace), but master can probably keep this commit if it brings tangible security benefits (and I think it does)
See the debian qemu-side of the bug for details:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1087822
Quoted 1 line
Is there an simple reproducer?
Unfortunately I couldn't get it to reproduce easily, but I think it's just a matter of finding the right binary that does problematic mappings (e.g. running true in a loop didn't work but running gcc in a loop did)
The most reliable reproducer I've been using is building a reasonably large program, we were working on modemmanager at the time so that's what I used; if usually fails between 100-300/500 of the build:
----
$ docker run -ti --rm --platform linux/arm64/v8 docker.io/arm64v8/alpine:3.20 sh / # apk add bash-completion-dev dbus-dev elogind-dev gobject-introspection-dev gtk-doc libgudev-dev libmbim-dev libqmi-dev linux-headers meson vala clang abuild alpine-sdk curl / # curl -O https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/archive/1.22.0/ModemManager-1.22.0.tar.gz / # tar xf ModemManager-1.22.0.tar.gz / # cd ModemManager-1.22.0/ / # abuild-meson \ -Db_lto=true \ -Dsystemdsystemunitdir=no \ -Ddbus_policy_dir=/usr/share/dbus-1/system.d \ -Dgtk_doc=true \ -Dsystemd_journal=false \ -Dsystemd_suspend_resume=true \ -Dvapi=true \ -Dpolkit=no \ . output / # meson compile -C output ----
If you take any of the command that failed from this build and run it in a loop, it'll also eventually fail after a couple hundred of invocations, but if your loop doesn't involve any parallelism that'll be slower to reproduce.
Note it requires qemu to be broken as well, so you'll have best chances with a debian bookworm (VM is fine; a chroot or podman instead of docker is also fine; in the chroot case ninja requires at least /dev (and possibly /proc) mounted)
Thanks,
Signature · 1 line
Dominique Martinet | Asmadeus
Greg Kroah-Hartman
maintainerPATCH 176/321 memory: stm32-fmc2-ebi: check regmap_read return value
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Kerello <[email protected]>
[ Upstream commit 722463f73bcf65a8c818752a38c14ee672c77da1 ]
Check regmap_read return value to avoid to use uninitialized local variables.
--- drivers/memory/stm32-fmc2-ebi.c | 122 +++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 34 deletions(-)
drivers/memory/stm32-fmc2-ebi.c +88 -34
@@ -179,8 +179,11 @@ static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi, int cs) {u32 bcr; +int ret; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret;if (bcr &FMC2_BCR_MTYP )return 0 ;
@@ -193,8 +196,11 @@ static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi, int cs) {u32 bcr, val =FIELD_PREP (FMC2_BCR_MTYP ,FMC2_BCR_MTYP_NOR ); +int ret; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret;if ((bcr &FMC2_BCR_MTYP ) == val && bcr &FMC2_BCR_BURSTEN )return 0 ;
@@ -207,8 +213,11 @@ static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi, int cs) {u32 bcr; +int ret; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret;if (bcr &FMC2_BCR_BURSTEN )return 0 ;
@@ -221,8 +230,11 @@ static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi, int cs) {u32 bcr; +int ret; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret;if (!(bcr &FMC2_BCR_BURSTEN ) || !(bcr &FMC2_BCR_CBURSTRW ))return 0 ;
@@ -235,8 +247,11 @@ static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi, int cs) {u32 bcr, val =FIELD_PREP (FMC2_BCR_MTYP ,FMC2_BCR_MTYP_PSRAM ); +int ret; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret;if ((bcr &FMC2_BCR_MTYP ) == val && bcr &FMC2_BCR_BURSTEN )return 0 ;
@@ -249,12 +264,18 @@ static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi, int cs) {u32 bcr, bxtr, val =FIELD_PREP (FMC2_BXTR_ACCMOD ,FMC2_BXTR_EXTMOD_D ); +int ret; + + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr);if (prop->reg_type ==FMC2_REG_BWTR ) -regmap_read (ebi->regmap,FMC2_BWTR (cs), &bxtr); + ret =regmap_read (ebi->regmap,FMC2_BWTR (cs), &bxtr);else -regmap_read (ebi->regmap,FMC2_BTR (cs), &bxtr); + ret =regmap_read (ebi->regmap,FMC2_BTR (cs), &bxtr); +if (ret) +return ret;if ((!(bcr &FMC2_BCR_BURSTEN ) || !(bcr &FMC2_BCR_CBURSTRW )) && ((bxtr &FMC2_BXTR_ACCMOD ) == val || bcr &FMC2_BCR_MUXEN ))
@@ -268,12 +289,19 @@ static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi, int cs) {u32 bcr, bcr1; +int ret; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); -if (cs) -regmap_read (ebi->regmap,FMC2_BCR1 , &bcr1); -else + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret; + +if (cs) { + ret =regmap_read (ebi->regmap,FMC2_BCR1 , &bcr1); +if (ret) +return ret; + }else { bcr1 = bcr; + }if (bcr &FMC2_BCR_BURSTEN && (!cs || !(bcr1 &FMC2_BCR1_CCLKEN )))return 0 ;
@@ -305,12 +333,18 @@ static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi, {u32 nb_clk_cycles =stm32_fmc2_ebi_ns_to_clock_cycles (ebi, cs, setup);u32 bcr, btr, clk_period; +int ret; + + ret =regmap_read (ebi->regmap,FMC2_BCR1 , &bcr); +if (ret) +return ret; -regmap_read (ebi->regmap,FMC2_BCR1 , &bcr);if (bcr &FMC2_BCR1_CCLKEN || !cs) -regmap_read (ebi->regmap,FMC2_BTR1 , &btr); + ret =regmap_read (ebi->regmap,FMC2_BTR1 , &btr);else -regmap_read (ebi->regmap,FMC2_BTR (cs), &btr); + ret =regmap_read (ebi->regmap,FMC2_BTR (cs), &btr); +if (ret) +return ret; clk_period =FIELD_GET (FMC2_BTR_CLKDIV , btr) +1 ;
@@ -569,11 +603,16 @@ static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi,if (ret)return ret; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret; +if (prop->reg_type ==FMC2_REG_BWTR ) -regmap_read (ebi->regmap,FMC2_BWTR (cs), &bxtr); + ret =regmap_read (ebi->regmap,FMC2_BWTR (cs), &bxtr);else -regmap_read (ebi->regmap,FMC2_BTR (cs), &bxtr); + ret =regmap_read (ebi->regmap,FMC2_BTR (cs), &bxtr); +if (ret) +return ret;if ((bxtr &FMC2_BXTR_ACCMOD ) == val || bcr &FMC2_BCR_MUXEN ) val =clamp_val (setup,1 ,FMC2_BXTR_ADDSET_MAX );
@@ -691,11 +730,14 @@ static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi, int cs, u32 setup) {u32 old_val, new_val, pcscntr; +int ret;if (setup <1 )return 0 ; -regmap_read (ebi->regmap,FMC2_PCSCNTR , &pcscntr); + ret =regmap_read (ebi->regmap,FMC2_PCSCNTR , &pcscntr); +if (ret) +return ret;/* Enable counter for the bank */ regmap_update_bits(ebi->regmap, FMC2_PCSCNTR,
@@ -942,17 +984,20 @@ static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs)regmap_update_bits (ebi->regmap,FMC2_BCR (cs),FMC2_BCR_MBKEN ,0 ); } -static void stm32_fmc2_ebi_save_setup (struct stm32_fmc2_ebi *ebi) +static int stm32_fmc2_ebi_save_setup (struct stm32_fmc2_ebi *ebi) {unsigned int cs; +int ret;for (cs =0 ; cs <FMC2_MAX_EBI_CE ; cs++) { -regmap_read (ebi->regmap,FMC2_BCR (cs), &ebi->bcr[cs]); -regmap_read (ebi->regmap,FMC2_BTR (cs), &ebi->btr[cs]); -regmap_read (ebi->regmap,FMC2_BWTR (cs), &ebi->bwtr[cs]); + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &ebi->bcr[cs]); + ret |=regmap_read (ebi->regmap,FMC2_BTR (cs), &ebi->btr[cs]); + ret |=regmap_read (ebi->regmap,FMC2_BWTR (cs), &ebi->bwtr[cs]); +if (ret) +return ret; } -regmap_read (ebi->regmap,FMC2_PCSCNTR , &ebi->pcscntr); +return regmap_read (ebi->regmap,FMC2_PCSCNTR , &ebi->pcscntr); }static void stm32_fmc2_ebi_set_setup (struct stm32_fmc2_ebi *ebi)
@@ -981,22 +1026,29 @@ static void stm32_fmc2_ebi_disable_banks(struct stm32_fmc2_ebi *ebi) }/* NWAIT signal can not be connected to EBI controller and NAND controller */ -static bool stm32_fmc2_ebi_nwait_used_by_ctrls (struct stm32_fmc2_ebi *ebi) +static int stm32_fmc2_ebi_nwait_used_by_ctrls (struct stm32_fmc2_ebi *ebi) { +struct device *dev = ebi->dev;unsigned int cs;u32 bcr; +int ret;for (cs =0 ; cs <FMC2_MAX_EBI_CE ; cs++) {if (!(ebi->bank_assigned &BIT (cs)))continue ; -regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); + ret =regmap_read (ebi->regmap,FMC2_BCR (cs), &bcr); +if (ret) +return ret; +if ((bcr &FMC2_BCR_WAITEN || bcr &FMC2_BCR_ASYNCWAIT ) && - ebi->bank_assigned &BIT (FMC2_NAND )) -return true; + ebi->bank_assigned &BIT (FMC2_NAND )) { +dev_err (dev,"NWAIT signal connected to EBI and NAND controllers\n" ); +return -EINVAL ; + } } -return false; +return 0 ; }static void stm32_fmc2_ebi_enable (struct stm32_fmc2_ebi *ebi)
@@ -1083,10 +1135,9 @@ static int stm32_fmc2_ebi_parse_dt(struct stm32_fmc2_ebi *ebi)return -ENODEV ; } -if (stm32_fmc2_ebi_nwait_used_by_ctrls (ebi)) { -dev_err (dev,"NWAIT signal connected to EBI and NAND controllers\n" ); -return -EINVAL ; - } + ret =stm32_fmc2_ebi_nwait_used_by_ctrls (ebi); +if (ret) +return ret;stm32_fmc2_ebi_enable (ebi);
@@ -1131,7 +1182,10 @@ static int stm32_fmc2_ebi_probe(struct platform_device *pdev)if (ret) goto err_release; -stm32_fmc2_ebi_save_setup (ebi); + ret =stm32_fmc2_ebi_save_setup (ebi); +if (ret) + goto err_release; +platform_set_drvdata (pdev, ebi);return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 177/321 parisc: Use irq_enter_rcu() to fix warning at kernel/context_tracking.c:367
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Helge Deller <[email protected]>
[ Upstream commit 73cb4a2d8d7e0259f94046116727084f21e4599f ]
Use irq*_rcu() functions to fix this kernel warning:
WARNING: CPU: 0 PID: 0 at kernel/context_tracking.c:367 ct_irq_enter+0xa0/0xd0 Modules linked in: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.7.0-rc3-64bit+ #1037 Hardware name: 9000/785/C3700
IASQ: 0000000000000000 0000000000000000 IAOQ: 00000000412cd758 00000000412cd75c
IIR: 03ffe01f ISR: 0000000000000000 IOR: 0000000043c20c20
CPU: 0 CR30: 0000000041caa000 CR31: 0000000000000000
ORIG_R28: 0000000000000005
IAOQ[0]: ct_irq_enter+0xa0/0xd0
IAOQ[1]: ct_irq_enter+0xa4/0xd0
RP(r2): irq_enter+0x34/0x68
Backtrace: [<000000004034a3ec>] irq_enter+0x34/0x68 [<000000004030dc48>] do_cpu_irq_mask+0xc0/0x450 [<0000000040303070>] intr_return+0x0/0xc
--- arch/parisc/kernel/irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/parisc/kernel/irq.c +2 -2
@@ -501,7 +501,7 @@ void do_cpu_irq_mask(struct pt_regs *regs) old_regs =set_irq_regs (regs);local_irq_disable (); -irq_enter (); +irq_enter_rcu (); eirr_val =mfctl (23 ) & cpu_eiem &per_cpu (local_ack_eiem, cpu);if (!eirr_val)
@@ -536,7 +536,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)#endif /* CONFIG_IRQSTACKS */ out: -irq_exit (); +irq_exit_rcu ();set_irq_regs (old_regs);return ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 178/321 powerpc/boot: Handle allocation failure in simple_realloc()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li zeming <[email protected]>
[ Upstream commit 69b0194ccec033c208b071e019032c1919c2822d ]
simple_malloc() will return NULL when there is not enough memory left. Check pointer 'new' before using it to copy the old data.
--- arch/powerpc/boot/simple_alloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/boot/simple_alloc.c +3 -1
@@ -112,7 +112,9 @@ static void *simple_realloc(void *ptr, unsigned long size)return ptr; new =simple_malloc (size); -memcpy (new, ptr, p->size); +if (new) +memcpy (new, ptr, p->size); +simple_free (ptr);return new; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 179/321 powerpc/boot: Only free if realloc() succeeds
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Ellerman <[email protected]>
[ Upstream commit f2d5bccaca3e8c09c9b9c8485375f7bdbb2631d2 ]
simple_realloc() frees the original buffer (ptr) even if the reallocation failed.
Fix it to behave like standard realloc() and only free the original buffer if the reallocation succeeded.
--- arch/powerpc/boot/simple_alloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/powerpc/boot/simple_alloc.c +3 -2
@@ -112,10 +112,11 @@ static void *simple_realloc(void *ptr, unsigned long size)return ptr; new =simple_malloc (size); -if (new) +if (new) {memcpy (new, ptr, p->size); +simple_free (ptr); + } -simple_free (ptr);return new; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 180/321 btrfs: delayed-inode: drop pointless BUG_ON in __btrfs_remove_delayed_item()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit 778e618b8bfedcc39354373c1b072c5fe044fa7b ]
There's a BUG_ON checking for a valid pointer of fs_info::delayed_root but it is valid since init_mount_fs_info() and has the same lifetime as fs_info.
--- fs/btrfs/delayed-inode.c | 2 -- 1 file changed, 2 deletions(-)
fs/btrfs/delayed-inode.c +0 -2
@@ -420,8 +420,6 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item) delayed_root = delayed_node->root->fs_info->delayed_root; -BUG_ON (!delayed_root); -if (delayed_item->type ==BTRFS_DELAYED_INSERTION_ITEM ) root = &delayed_node->ins_root;else
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 181/321 btrfs: change BUG_ON to assertion when checking for delayed_node root
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit be73f4448b607e6b7ce41cd8ef2214fdf6e7986f ]
The pointer to root is initialized in btrfs_init_delayed_node(), no need to check for it again. Change the BUG_ON to assertion.
--- fs/btrfs/delayed-inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/delayed-inode.c +1 -1
@@ -968,7 +968,7 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node)if (delayed_node &&test_bit (BTRFS_DELAYED_NODE_INODE_DIRTY , &delayed_node->flags)) { -BUG_ON (!delayed_node->root); +ASSERT (delayed_node->root);clear_bit (BTRFS_DELAYED_NODE_INODE_DIRTY , &delayed_node->flags); delayed_node->count--;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 182/321 btrfs: tests: allocate dummy fs_info and root in test_find_delalloc()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit b2136cc288fce2f24a92f3d656531b2d50ebec5a ]
Allocate fs_info and root to have a valid fs_info pointer in case it's dereferenced by a helper outside of tests, like find_lock_delalloc_range().
--- fs/btrfs/tests/extent-io-tests.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)
fs/btrfs/tests/extent-io-tests.c +24 -4
@@ -11,6 +11,7 @@#include "btrfs-tests.h" #include "../ctree.h" #include "../extent_io.h" +#include "../disk-io.h" #include "../btrfs_inode.h" #define PROCESS_UNLOCK (1 << 0)
@@ -105,9 +106,11 @@ static void dump_extent_io_tree(const struct extent_io_tree *tree) } } -static int test_find_delalloc (u32 sectorsize) +static int test_find_delalloc (u32 sectorsize,u32 nodesize) { -struct inode *inode; +struct btrfs_fs_info *fs_info; +struct btrfs_root *root =NULL ; +struct inode *inode =NULL ;struct extent_io_tree *tmp;struct page *page;struct page *locked_page =NULL ;
@@ -121,12 +124,27 @@ static int test_find_delalloc(u32 sectorsize)test_msg ("running find delalloc tests" ); + fs_info =btrfs_alloc_dummy_fs_info (nodesize, sectorsize); +if (!fs_info) { +test_std_err (TEST_ALLOC_FS_INFO ); +return -ENOMEM ; + } + + root =btrfs_alloc_dummy_root (fs_info); +if (IS_ERR (root)) { +test_std_err (TEST_ALLOC_ROOT ); + ret =PTR_ERR (root); + goto out; + } + inode =btrfs_new_test_inode ();if (!inode) {test_std_err (TEST_ALLOC_INODE ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out; } tmp = &BTRFS_I (inode)->io_tree; +BTRFS_I (inode)->root = root;/* * Passing NULL as we don't have fs_info but tracepoints are not used
@@ -316,6 +334,8 @@ static int test_find_delalloc(u32 sectorsize)process_page_range (inode,0 , total_dirty -1 ,PROCESS_UNLOCK |PROCESS_RELEASE );iput (inode); +btrfs_free_dummy_root (root); +btrfs_free_dummy_fs_info (fs_info);return ret; }
@@ -598,7 +618,7 @@ int btrfs_test_extent_io(u32 sectorsize, u32 nodesize)test_msg ("running extent I/O tests" ); - ret =test_find_delalloc (sectorsize); + ret =test_find_delalloc (sectorsize, nodesize);if (ret) goto out;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 183/321 btrfs: handle invalid root reference found in may_destroy_subvol()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit 6fbc6f4ac1f4907da4fc674251527e7dc79ffbf6 ]
The may_destroy_subvol() looks up a root by a key, allowing to do an inexact search when key->offset is -1. It's never expected to find such item, as it would break the allowed range of a root id.
--- fs/btrfs/inode.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
fs/btrfs/inode.c +8 -1
@@ -4614,7 +4614,14 @@ static noinline int may_destroy_subvol(struct btrfs_root *root) ret =btrfs_search_slot (NULL , fs_info->tree_root, &key, path,0 ,0 );if (ret <0 ) goto out; -BUG_ON (ret ==0 ); +if (ret ==0 ) { +/* +* Key with offset -1 found, there would have to exist a root +* with such id, but this is out of valid range. +*/ + ret = -EUCLEAN ; + goto out; + } ret =0 ;if (path->slots[0 ] >0 ) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 184/321 btrfs: send: handle unexpected data in header buffer in begin_cmd()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit e80e3f732cf53c64b0d811e1581470d67f6c3228 ]
Change BUG_ON to a proper error handling in the unlikely case of seeing data when the command is started. This is supposed to be reset when the command is finished (send_cmd, send_encoded_extent).
--- fs/btrfs/send.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/btrfs/send.c +6 -1
@@ -720,7 +720,12 @@ static int begin_cmd(struct send_ctx *sctx, int cmd)if (WARN_ON (!sctx->send_buf))return -EINVAL ; -BUG_ON (sctx->send_size); +if (unlikely (sctx->send_size !=0 )) { +btrfs_err (sctx->send_root->fs_info, +"send: command header buffer not empty cmd %d offset %llu" , + cmd, sctx->send_off); +return -EINVAL ; + } sctx->send_size +=sizeof (*hdr); hdr = (struct btrfs_cmd_header *)sctx->send_buf;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 185/321 btrfs: change BUG_ON to assertion in tree_move_down()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit 56f335e043ae73c32dbb70ba95488845dc0f1e6e ]
There's only one caller of tree_move_down() that does not pass level 0 so the assertion is better suited here.
--- fs/btrfs/send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/send.c +1 -1
@@ -7185,8 +7185,8 @@ static int tree_move_down(struct btrfs_path *path, int *level, u64 reada_min_genu64 reada_done =0 ;lockdep_assert_held_read (&parent->fs_info->commit_root_sem); +ASSERT (*level !=0 ); -BUG_ON (*level ==0 ); eb =btrfs_read_node_slot (parent, slot);if (IS_ERR (eb))return PTR_ERR (eb);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 186/321 btrfs: delete pointless BUG_ON check on quota root in btrfs_qgroup_account_extent()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit f40a3ea94881f668084f68f6b9931486b1606db0 ]
The BUG_ON is deep in the qgroup code where we can expect that it exists. A NULL pointer would cause a crash.
It was added long ago in 550d7a2ed5db35 ("btrfs: qgroup: Add new qgroup calculation function btrfs_qgroup_account_extents()."). It maybe made sense back then as the quota enable/disable state machine was not that robust as it is nowadays, so we can just delete it.
--- fs/btrfs/qgroup.c | 2 -- 1 file changed, 2 deletions(-)
fs/btrfs/qgroup.c +0 -2
@@ -2697,8 +2697,6 @@ int btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,if (nr_old_roots ==0 && nr_new_roots ==0 ) goto out_free; -BUG_ON (!fs_info->quota_root); -trace_btrfs_qgroup_account_extent (fs_info, trans->transid, bytenr, num_bytes, nr_old_roots, nr_new_roots);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 187/321 f2fs: fix to do sanity check in update_sit_entry
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiguo Niu <[email protected]>
[ Upstream commit 36959d18c3cf09b3c12157c6950e18652067de77 ]
If GET_SEGNO return NULL_SEGNO for some unecpected case, update_sit_entry will access invalid memory address, cause system crash. It is better to do sanity check about GET_SEGNO just like update_segment_mtime & locate_dirty_segment.
Also remove some redundant judgment code.
--- fs/f2fs/segment.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/f2fs/segment.c +3 -2
@@ -2191,6 +2191,8 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)#endif segno =GET_SEGNO (sbi, blkaddr); +if (segno ==NULL_SEGNO ) +return ; se =get_seg_entry (sbi, segno); new_vblocks = se->valid_blocks + del;
@@ -3286,8 +3288,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,* since SSR needs latest valid block information. */ update_sit_entry (sbi, *new_blkaddr,1 ); -if (GET_SEGNO (sbi, old_blkaddr) !=NULL_SEGNO ) -update_sit_entry (sbi, old_blkaddr,-1 ); +update_sit_entry (sbi, old_blkaddr,-1 );if (!__has_curseg_space (sbi, curseg)) {if (from_gc)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 188/321 usb: gadget: fsl: Increase size of name buffer for endpoints
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 87850f6cc20911e35eafcbc1d56b0d649ae9162d ]
This fixes a W=1 warning about sprintf writing up to 16 bytes into a buffer of size 14. There is no practical relevance because there are not more than 32 endpoints.
--- drivers/usb/gadget/udc/fsl_udc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/udc/fsl_udc_core.c +1 -1
@@ -2487,7 +2487,7 @@ static int fsl_udc_probe(struct platform_device *pdev)/* setup the udc->eps[] for non-control endpoints and link * to gadget.ep_list */ for (i =1 ; i < (int )(udc_controller->max_ep /2 ); i++) { -char name[14 ]; +char name[16 ];sprintf (name,"ep%dout" , i);struct_ep_setup (udc_controller, i *2 , name,1 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 189/321 nvme: clear caller pointer on identify failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Keith Busch <[email protected]>
[ Upstream commit 7e80eb792bd7377a20f204943ac31c77d859be89 ]
The memory allocated for the identification is freed on failure. Set it to NULL so the caller doesn't have a pointer to that freed address.
--- drivers/nvme/host/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/nvme/host/core.c +4 -1
@@ -1366,8 +1366,10 @@ static int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id) error =nvme_submit_sync_cmd (dev->admin_q, &c, *id,sizeof (struct nvme_id_ctrl )); -if (error) +if (error) {kfree (*id); + *id =NULL ; + }return error; }
@@ -1496,6 +1498,7 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,if (error) {dev_warn (ctrl->device,"Identify namespace failed (%d)\n" , error);kfree (*id); + *id =NULL ; }return error; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 190/321 Bluetooth: bnep: Fix out-of-bound access
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 0f0639b4d6f649338ce29c62da3ec0787fa08cd1 ]
This fixes attempting to access past ethhdr.h_source, although it seems intentional to copy also the contents of h_proto this triggers out-of-bound access problems with the likes of static analyzer, so this instead just copy ETH_ALEN and then proceed to use put_unaligned to copy h_proto separetely.
--- net/bluetooth/bnep/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/bluetooth/bnep/core.c +2 -1
@@ -385,7 +385,8 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)case BNEP_COMPRESSED_DST_ONLY :__skb_put_data (nskb,skb_mac_header (skb),ETH_ALEN ); -__skb_put_data (nskb, s->eh.h_source,ETH_ALEN +2 ); +__skb_put_data (nskb, s->eh.h_source,ETH_ALEN ); +put_unaligned (s->eh.h_proto, (__be16 *)__skb_put (nskb,2 ));break ;case BNEP_GENERAL :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 191/321 firmware: cirrus: cs_dsp: Initialize debugfs_root to invalid
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <[email protected]>
[ Upstream commit 66626b15636b5f5cf3d7f6104799f77462748974 ]
Initialize debugfs_root to -ENODEV so that if the client never sets a valid debugfs root the debugfs files will not be created.
A NULL pointer passed to any of the debugfs_create_*() functions means "create in the root of debugfs". It doesn't mean "ignore".
--- drivers/firmware/cirrus/cs_dsp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/firmware/cirrus/cs_dsp.c +6 -1
@@ -490,7 +490,7 @@ void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp) {cs_dsp_debugfs_clear (dsp);debugfs_remove_recursive (dsp->debugfs_root); - dsp->debugfs_root =NULL ; + dsp->debugfs_root =ERR_PTR (-ENODEV ); }EXPORT_SYMBOL_GPL (cs_dsp_cleanup_debugfs);#else
@@ -2300,6 +2300,11 @@ static int cs_dsp_common_init(struct cs_dsp *dsp)mutex_init (&dsp->pwr_lock); +#ifdef CONFIG_DEBUG_FS +/* Ensure this is invalid if client never provides a debugfs root */ + dsp->debugfs_root =ERR_PTR (-ENODEV ); +#endif +return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 192/321 rtc: nct3018y: fix possible NULL dereference
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandre Belloni <[email protected]>
[ Upstream commit babfeb9cbe7ebc657bd5b3e4f9fde79f560b6acc ]
alarm_enable and alarm_flag are allowed to be NULL but will be dereferenced later by the dev_dbg call.
--- drivers/rtc/rtc-nct3018y.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/rtc/rtc-nct3018y.c +3 -3
@@ -99,6 +99,8 @@ static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *alaif (flags <0 )return flags; *alarm_enable = flags &NCT3018Y_BIT_AIE ; +dev_dbg (&client->dev,"%s:alarm_enable:%x\n" , __func__, *alarm_enable); + }if (alarm_flag) {
@@ -107,11 +109,9 @@ static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *alaif (flags <0 )return flags; *alarm_flag = flags &NCT3018Y_BIT_AF ; +dev_dbg (&client->dev,"%s:alarm_flag:%x\n" , __func__, *alarm_flag); } -dev_dbg (&client->dev,"%s:alarm_enable:%x alarm_flag:%x\n" , - __func__, *alarm_enable, *alarm_flag); -return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 193/321 net: hns3: add checking for vf id of mailbox
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jian Shen <[email protected]>
[ Upstream commit 4e2969a0d6a7549bc0bc1ebc990588b622c4443d ]
Add checking for vf id of mailbox, in order to avoid array out-of-bounds risk.
--- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +4 -3
@@ -1124,10 +1124,11 @@ void hclge_mbx_handler(struct hclge_dev *hdev) req = (struct hclge_mbx_vf_to_pf_cmd *)desc->data; flag =le16_to_cpu (crq->desc[crq->next_to_use].flag); -if (unlikely (!hnae3_get_bit (flag,HCLGE_CMDQ_RX_OUTVLD_B ))) { +if (unlikely (!hnae3_get_bit (flag,HCLGE_CMDQ_RX_OUTVLD_B ) || + req->mbx_src_vfid > hdev->num_req_vfs)) {dev_warn (&hdev->pdev->dev, -"dropped invalid mailbox message, code = %u\n" , - req->msg.code); +"dropped invalid mailbox message, code = %u, vfid = %u\n" , + req->msg.code, req->mbx_src_vfid);/* dropping/not processing this invalid message */ crq->desc[crq->next_to_use].flag =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 194/321 nvmet-tcp: do not continue for invalid icreq
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Reinecke <[email protected]>
[ Upstream commit 0889d13b9e1cbef49e802ae09f3b516911ad82a1 ]
When the length check for an icreq sqe fails we should not continue processing but rather return immediately as all other contents of that sqe cannot be relied on.
--- drivers/nvme/target/tcp.c | 1 + 1 file changed, 1 insertion(+)
drivers/nvme/target/tcp.c +1 -0
@@ -836,6 +836,7 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)pr_err ("bad nvme-tcp pdu length (%d)\n" ,le32_to_cpu (icreq->hdr.plen));nvmet_tcp_fatal_error (queue); +return -EPROTO ; }if (icreq->pfv !=NVME_TCP_PFV_1_0 ) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 195/321 NFS: avoid infinite loop in pnfs_update_layout.
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 2fdbc20036acda9e5694db74a032d3c605323005 ]
If pnfsd_update_layout() is called on a file for which recovery has failed it will enter a tight infinite loop.
NFS_LAYOUT_INVALID_STID will be set, nfs4_select_rw_stateid() will return -EIO, and nfs4_schedule_stateid_recovery() will do nothing, so nfs4_client_recover_expired_lease() will not wait. So the code will loop indefinitely.
Break the loop by testing the validity of the open stateid at the top of the loop.
--- fs/nfs/pnfs.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/nfs/pnfs.c +8 -0
@@ -1997,6 +1997,14 @@ pnfs_update_layout(struct inode *ino, } lookup_again: +if (!nfs4_valid_open_stateid (ctx->state)) { +trace_pnfs_update_layout (ino, pos, count, + iomode, lo, lseg, +PNFS_UPDATE_LAYOUT_INVALID_OPEN ); + lseg =ERR_PTR (-EIO ); + goto out; + } + lseg =ERR_PTR (nfs4_client_recover_expired_lease (clp));if (IS_ERR (lseg)) goto out;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 196/321 openrisc: Call setup_memory() earlier in the init sequence
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oreoluwa Babatunde <[email protected]>
[ Upstream commit 7b432bf376c9c198a7ff48f1ed14a14c0ffbe1fe ]
The unflatten_and_copy_device_tree() function contains a call to memblock_alloc(). This means that memblock is allocating memory before any of the reserved memory regions are set aside in the setup_memory() function which calls early_init_fdt_scan_reserved_mem(). Therefore, there is a possibility for memblock to allocate from any of the reserved memory regions.
Hence, move the call to setup_memory() to be earlier in the init sequence so that the reserved memory regions are set aside before any allocations are done using memblock.
--- arch/openrisc/kernel/setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/openrisc/kernel/setup.c +3 -3
@@ -270,6 +270,9 @@ void calibrate_delay(void)void __init setup_arch (char **cmdline_p) { +/* setup memblock allocator */ +setup_memory (); +unflatten_and_copy_device_tree ();setup_cpuinfo ();
@@ -293,9 +296,6 @@ void __init setup_arch(char **cmdline_p) }#endif -/* setup memblock allocator */ -setup_memory (); -/* paging_init() sets up the MMU and marks all pages as reserved */ paging_init ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 197/321 s390/iucv: fix receive buffer virtual vs physical address confusion
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Gordeev <[email protected]>
[ Upstream commit 4e8477aeb46dfe74e829c06ea588dd00ba20c8cc ]
Fix IUCV_IPBUFLST-type buffers virtual vs physical address confusion. This does not fix a bug since virtual and physical address spaces are currently the same.
--- net/iucv/iucv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/iucv/iucv.c +1 -2
@@ -1090,8 +1090,7 @@ static int iucv_message_receive_iprmdata(struct iucv_path *path, size = (size <8 ) ? size :8 ;for (array = buffer; size >0 ; array++) { copy =min_t (size_t, size, array->length); -memcpy ((u8 *)(addr_t ) array->address, - rmmsg, copy); +memcpy (phys_to_virt (array->address), rmmsg, copy); rmmsg += copy; size -= copy; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 198/321 irqchip/renesas-rzg2l: Do not set TIEN and TINT source at the same time
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Biju Das <[email protected]>
[ Upstream commit dce0919c83c325ac9dec5bc8838d5de6d32c01b1 ]
As per the hardware team, TIEN and TINT source should not set at the same time due to a possible hardware race leading to spurious IRQ.
Currently on some scenarios hardware settings for TINT detection is not in sync with TINT source as the enable/disable overrides source setting value leading to hardware inconsistent state. For eg: consider the case GPIOINT0 is used as TINT interrupt and configuring GPIOINT5 as edge type. During rzg2l_irq_set_type(), TINT source for GPIOINT5 is set. On disable(), clearing of the entire bytes of TINT source selection for GPIOINT5 is same as GPIOINT0 with TIEN disabled. Apart from this during enable(), the setting of GPIOINT5 with TIEN results in spurious IRQ as due to a HW race, it is possible that IP can use the TIEN with previous source value (GPIOINT0).
So, just update TIEN during enable/disable as TINT source is already set during rzg2l_irq_set_type(). This will make the consistent hardware settings for detection method tied with TINT source and allows to simplify the code.
--- drivers/irqchip/irq-renesas-rzg2l.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/irqchip/irq-renesas-rzg2l.c +2 -3
@@ -132,7 +132,7 @@ static void rzg2l_irqc_irq_disable(struct irq_data *d)raw_spin_lock (&priv->lock); reg =readl_relaxed (priv->base +TSSR (tssr_index)); - reg &= ~(TSSEL_MASK <<TSSEL_SHIFT (tssr_offset)); + reg &= ~(TIEN <<TSSEL_SHIFT (tssr_offset));writel_relaxed (reg, priv->base +TSSR (tssr_index));raw_spin_unlock (&priv->lock); }
@@ -145,7 +145,6 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)if (hw_irq >=IRQC_TINT_START && hw_irq <IRQC_NUM_IRQ ) {struct rzg2l_irqc_priv *priv =irq_data_to_priv (d); -unsigned long tint = (uintptr_t )d->chip_data;u32 offset = hw_irq -IRQC_TINT_START ;u32 tssr_offset =TSSR_OFFSET (offset);u8 tssr_index =TSSR_INDEX (offset);
@@ -153,7 +152,7 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)raw_spin_lock (&priv->lock); reg =readl_relaxed (priv->base +TSSR (tssr_index)); - reg |= (TIEN | tint) <<TSSEL_SHIFT (tssr_offset); + reg |=TIEN <<TSSEL_SHIFT (tssr_offset);writel_relaxed (reg, priv->base +TSSR (tssr_index));raw_spin_unlock (&priv->lock); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 199/321 clocksource: Make watchdog and suspend-timing multiplication overflow safe
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
[ Upstream commit d0304569fb019d1bcfbbbce1ce6df6b96f04079b ]
Kernel timekeeping is designed to keep the change in cycles (since the last timer interrupt) below max_cycles, which prevents multiplication overflow when converting cycles to nanoseconds. However, if timer interrupts stop, the clocksource_cyc2ns() calculation will eventually overflow.
Add protection against that. Simplify by folding together clocksource_delta() and clocksource_cyc2ns() into cycles_to_nsec_safe(). Check against max_cycles, falling back to a slower higher precision calculation.
--- kernel/time/clocksource.c | 42 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 22 deletions(-)
kernel/time/clocksource.c +20 -22
@@ -20,6 +20,16 @@#include "tick-internal.h" #include "timekeeping_internal.h" +static noinline u64 cycles_to_nsec_safe(struct clocksource *cs, u64 start, u64 end) +{ +u64 delta =clocksource_delta (end, start, cs->mask); + +if (likely (delta < cs->max_cycles)) +return clocksource_cyc2ns (delta, cs->mult, cs->shift); + +return mul_u64_u32_shr (delta, cs->mult, cs->shift); +} +/** * clocks_calc_mult_shift - calculate mult/shift factors for scaled math of clocks * @mult: pointer to mult variable
@@ -219,8 +229,8 @@ enum wd_read_status {static enum wd_read_status cs_watchdog_read (struct clocksource *cs,u64 *csnow,u64 *wdnow) {unsigned int nretries, max_retries; -u64 wd_end, wd_end2, wd_delta;int64_t wd_delay, wd_seq_delay; +u64 wd_end, wd_end2; max_retries =clocksource_get_max_watchdog_retry ();for (nretries =0 ; nretries <= max_retries; nretries++) {
@@ -231,9 +241,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, wd_end2 = watchdog->read (watchdog);local_irq_enable (); - wd_delta =clocksource_delta (wd_end, *wdnow, watchdog->mask); - wd_delay =clocksource_cyc2ns (wd_delta, watchdog->mult, - watchdog->shift); + wd_delay =cycles_to_nsec_safe (watchdog, *wdnow, wd_end);if (wd_delay <=WATCHDOG_MAX_SKEW ) {if (nretries >1 && nretries >= max_retries) { pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n",
@@ -251,8 +259,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow,* report system busy, reinit the watchdog and skip the current * watchdog test. */ - wd_delta =clocksource_delta (wd_end2, wd_end, watchdog->mask); - wd_seq_delay =clocksource_cyc2ns (wd_delta, watchdog->mult, watchdog->shift); + wd_seq_delay =cycles_to_nsec_safe (watchdog, wd_end, wd_end2);if (wd_seq_delay >WATCHDOG_MAX_SKEW /2 ) goto skip_test; }
@@ -363,8 +370,7 @@ void clocksource_verify_percpu(struct clocksource *cs) delta = (csnow_end - csnow_mid) & cs->mask;if (delta <0 )cpumask_set_cpu (cpu, &cpus_ahead); - delta =clocksource_delta (csnow_end, csnow_begin, cs->mask); - cs_nsec =clocksource_cyc2ns (delta, cs->mult, cs->shift); + cs_nsec =cycles_to_nsec_safe (cs, csnow_begin, csnow_end);if (cs_nsec > cs_nsec_max) cs_nsec_max = cs_nsec;if (cs_nsec < cs_nsec_min)
@@ -395,8 +401,8 @@ static inline void clocksource_reset_watchdog(void)static void clocksource_watchdog (struct timer_list *unused) { -u64 csnow, wdnow, cslast, wdlast, delta;int64_t wd_nsec, cs_nsec, interval; +u64 csnow, wdnow, cslast, wdlast;int next_cpu, reset_pending;struct clocksource *cs;enum wd_read_status read_ret;
@@ -453,12 +459,8 @@ static void clocksource_watchdog(struct timer_list *unused)continue ; } - delta =clocksource_delta (wdnow, cs->wd_last, watchdog->mask); - wd_nsec =clocksource_cyc2ns (delta, watchdog->mult, - watchdog->shift); - - delta =clocksource_delta (csnow, cs->cs_last, cs->mask); - cs_nsec =clocksource_cyc2ns (delta, cs->mult, cs->shift); + wd_nsec =cycles_to_nsec_safe (watchdog, cs->wd_last, wdnow); + cs_nsec =cycles_to_nsec_safe (cs, cs->cs_last, csnow); wdlast = cs->wd_last;/* save these in case we print them */ cslast = cs->cs_last; cs->cs_last = csnow;
@@ -821,7 +823,7 @@ void clocksource_start_suspend_timing(struct clocksource *cs, u64 start_cycles)*/ u64 clocksource_stop_suspend_timing (struct clocksource *cs,u64 cycle_now) { -u64 now, delta, nsec =0 ; +u64 now, nsec =0 ;if (!suspend_clocksource)return 0 ;
@@ -836,12 +838,8 @@ u64 clocksource_stop_suspend_timing(struct clocksource *cs, u64 cycle_now)else now = suspend_clocksource->read (suspend_clocksource); -if (now > suspend_start) { - delta =clocksource_delta (now, suspend_start, - suspend_clocksource->mask); - nsec =mul_u64_u32_shr (delta, suspend_clocksource->mult, - suspend_clocksource->shift); - } +if (now > suspend_start) + nsec =cycles_to_nsec_safe (suspend_clocksource, suspend_start, now);/* * Disable the suspend timer to save power if current clocksource is
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 200/321 platform/x86: lg-laptop: fix %s null argument warning
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gergo Koteles <[email protected]>
[ Upstream commit e71c8481692582c70cdfd0996c20cdcc71e425d3 ]
W=1 warns about null argument to kprintf:
warning: ‘%s’ directive argument is null [-Wformat-overflow=] pr_info("product: %s year: %d\n", product, year);
Use "unknown" instead of NULL.
--- drivers/platform/x86/lg-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/platform/x86/lg-laptop.c +1 -1
@@ -715,7 +715,7 @@ static int acpi_add(struct acpi_device *device)default : year =2019 ; } -pr_info ("product: %s year: %d\n" , product, year); +pr_info ("product: %s year: %d\n" , product ?:"unknown" , year);if (year >=2019 ) battery_limit_use_wmbb =1 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 201/321 usb: dwc3: core: Skip setting event buffers for host only controllers
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krishna Kurapati <[email protected]>
[ Upstream commit 89d7f962994604a3e3d480832788d06179abefc5 ]
On some SoC's like SA8295P where the tertiary controller is host-only capable, GEVTADDRHI/LO, GEVTSIZ, GEVTCOUNT registers are not accessible. Trying to access them leads to a crash.
For DRD/Peripheral supported controllers, event buffer setup is done again in gadget_pullup. Skip setup or cleanup of event buffers if controller is host-only capable.
--- drivers/usb/dwc3/core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/usb/dwc3/core.c +13 -0
@@ -506,6 +506,13 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)static int dwc3_alloc_event_buffers (struct dwc3 *dwc,unsigned int length) {struct dwc3_event_buffer *evt; +unsigned int hw_mode; + + hw_mode =DWC3_GHWPARAMS0_MODE (dwc->hwparams.hwparams0); +if (hw_mode ==DWC3_GHWPARAMS0_MODE_HOST ) { + dwc->ev_buf =NULL ; +return 0 ; + } evt =dwc3_alloc_one_event_buffer (dwc, length);if (IS_ERR (evt)) {
@@ -527,6 +534,9 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc) {struct dwc3_event_buffer *evt; +if (!dwc->ev_buf) +return 0 ; + evt = dwc->ev_buf; evt->lpos =0 ; dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0),
@@ -544,6 +554,9 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc) {struct dwc3_event_buffer *evt; +if (!dwc->ev_buf) +return ; + evt = dwc->ev_buf; evt->lpos =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 202/321 fbdev: offb: replace of_node_put with __free(device_node)
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdulrasaq Lawani <[email protected]>
[ Upstream commit ce4a7ae84a58b9f33aae8d6c769b3c94f3d5ce76 ]
Replaced instance of of_node_put with __free(device_node) to simplify code and protect against any memory leaks due to future changes in the control flow.
--- drivers/video/fbdev/offb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/video/fbdev/offb.c +1 -2
@@ -355,7 +355,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp par->cmap_type = cmap_gxt2000; }else if (of_node_name_prefix (dp,"vga,Display-" )) {/* Look for AVIVO initialized by SLOF */ -struct device_node *pciparent =of_get_parent (dp); + struct device_node *pciparent __free(device_node) = of_get_parent(dp);const u32 *vid, *did; vid =of_get_property (pciparent,"vendor-id" ,NULL ); did =of_get_property (pciparent,"device-id" ,NULL );
@@ -367,7 +367,6 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dpif (par->cmap_adr) par->cmap_type = cmap_avivo; } -of_node_put (pciparent); }else if (dp &&of_device_is_compatible (dp,"qemu,std-vga" )) {#ifdef __BIG_ENDIANconst __be32 io_of_addr[3 ] = {0x01000000 ,0x0 ,0x0 };
Signature · 1 line
2.43.0
Re: [PATCH 6.1 202/321] fbdev: offb: replace of_node_put with __free(device_node)
Greg, Sasha,
Quoted 1 line · Greg Kroah-Hartman
6.1-stable review patch. If anyone has any objections, please let me know.
We got v6.1.107 build error on ppc64le due to this commit, with:
CC drivers/video/fbdev/offb.o
drivers/video/fbdev/offb.c: In function 'offb_init_palette_hacks':
drivers/video/fbdev/offb.c:358:24: error: cleanup argument not a function
358 | struct device_node *pciparent __free(device_node) = of_get_parent(dp);
| ^~~~~~~~~~~ make[4]: *** [scripts/Makefile.build:250: drivers/video/fbdev/offb.o] Error 1
Where CONFIG_FB_OF is enabled. Perhaps, due to this commit not being picked:
9448e55d032d ("of: Add cleanup.h based auto release via __free(device_node) markings")
Thanks,
Quoted 45 lines
------------------
From: Abdulrasaq Lawani <[email protected]>
[ Upstream commit
ce4a7ae84a58b9f33aae8d6c769b3c94f3d5ce76]Replaced instance of
of_node_putwith__free(device_node)to simplify code and protect against any memory leaks due to future changes in the control flow.Suggested-by Julia Lawall <[email protected]>Signed-off-by Abdulrasaq Lawani <[email protected]>Signed-off-by Helge Deller <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- drivers/video/fbdev/offb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)drivers/video/fbdev/offb.c +1
-2@@ -355,7 +355,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp par->cmap_type = cmap_gxt2000; }else if (of_node_name_prefix (dp,"vga,Display-" )) {/* Look for AVIVO initialized by SLOF */ -struct device_node *pciparent =of_get_parent (dp); + struct device_node *pciparent __free(device_node) = of_get_parent(dp);const u32 *vid, *did; vid =of_get_property (pciparent,"vendor-id" ,NULL ); did =of_get_property (pciparent,"device-id" ,NULL );@@ -367,7 +367,6 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dpif (par->cmap_adr) par->cmap_type = cmap_avivo; } -of_node_put (pciparent); }else if (dp &&of_device_is_compatible (dp,"qemu,std-vga" )) {#ifdef __BIG_ENDIANconst __be32 io_of_addr[3 ] = {0x01000000 ,0x0 ,0x0 };Signature · 1 line
2.43.0
Re: [PATCH 6.1 202/321] fbdev: offb: replace of_node_put with __free(device_node)
Greg,
Quoted 10 lines · Vitaly Chikunov
Greg, Sasha,
Quoted 1 line · Greg Kroah-Hartman
6.1-stable review patch. If anyone has any objections, please let me know.
We got v6.1.107 build error on ppc64le due to this commit, with:
CC
drivers/video/fbdev/offb.o
drivers/video/fbdev/offb.c: In function 'offb_init_palette_hacks':
drivers/video/fbdev/offb.c:358:24: error: cleanup argument not a function
Quoted 7 lines
358 | struct device_node *pciparent __free(device_node) = of_get_parent(dp); | ^~~~~~~~~~~make[4]: *** [
scripts/Makefile.build:250:drivers/video/fbdev/offb.o] Error 1Where
CONFIG_FB_OFis enabled. Perhaps, due to this commit not being picked:
9448e55d032d("of: Addcleanup.hbased auto release via__free(device_node)markings")
I just tested, and cherry-picking this commit over 6.1.107 fixes the build on ppc64le with CONFIG_FB_OF=y.
Thanks,
Quoted 48 lines
Thanks,
Quoted 45 lines
------------------
From: Abdulrasaq Lawani <[email protected]>
[ Upstream commit
ce4a7ae84a58b9f33aae8d6c769b3c94f3d5ce76]Replaced instance of
of_node_putwith__free(device_node)to simplify code and protect against any memory leaks due to future changes in the control flow.Suggested-by Julia Lawall <[email protected]>Signed-off-by Abdulrasaq Lawani <[email protected]>Signed-off-by Helge Deller <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- drivers/video/fbdev/offb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)drivers/video/fbdev/offb.c +1
-2@@ -355,7 +355,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp par->cmap_type = cmap_gxt2000; }else if (of_node_name_prefix (dp,"vga,Display-" )) {/* Look for AVIVO initialized by SLOF */ -struct device_node *pciparent =of_get_parent (dp); + struct device_node *pciparent __free(device_node) = of_get_parent(dp);const u32 *vid, *did; vid =of_get_property (pciparent,"vendor-id" ,NULL ); did =of_get_property (pciparent,"device-id" ,NULL );@@ -367,7 +367,6 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dpif (par->cmap_adr) par->cmap_type = cmap_avivo; } -of_node_put (pciparent); }else if (dp &&of_device_is_compatible (dp,"qemu,std-vga" )) {#ifdef __BIG_ENDIANconst __be32 io_of_addr[3 ] = {0x01000000 ,0x0 ,0x0 };Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 203/321 irqchip/gic-v3-its: Remove BUG_ON in its_vpe_irq_domain_alloc
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanrui Huang <[email protected]>
[ Upstream commit 382d2ffe86efb1e2fa803d2cf17e5bfc34e574f3 ]
This BUG_ON() is useless, because the same effect will be obtained by letting the code run its course and vm being dereferenced, triggering an exception.
So just remove this check.
--- drivers/irqchip/irq-gic-v3-its.c | 2 -- 1 file changed, 2 deletions(-)
drivers/irqchip/irq-gic-v3-its.c +0 -2
@@ -4476,8 +4476,6 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virqstruct page *vprop_page;int base, nr_ids, i, err =0 ; -BUG_ON (!vm); - bitmap =its_lpi_alloc (roundup_pow_of_two (nr_irqs), &base, &nr_ids);if (!bitmap)return -ENOMEM ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 204/321 ext4: set the type of max_zeroout to unsigned int to avoid overflow
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 261341a932d9244cbcd372a3659428c8723e5a49 ]
The max_zeroout is of type int and the s_extent_max_zeroout_kb is of type uint, and the s_extent_max_zeroout_kb can be freely modified via the sysfs interface. When the block size is 1024, max_zeroout may overflow, so declare it as unsigned int to avoid overflow.
--- fs/ext4/extents.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ext4/extents.c +2 -1
@@ -3404,9 +3404,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,struct ext4_extent *ex, *abut_ex;ext4_lblk_t ee_block, eof_block;unsigned int ee_len, depth, map_len = map->m_len; -int allocated =0 , max_zeroout =0 ;int err =0 ;int split_flag =EXT4_EXT_DATA_VALID2 ; +int allocated =0 ; +unsigned int max_zeroout =0 ;ext_debug (inode,"logical block %llu, max_blocks %u\n" , (unsigned long long )map->m_lblk, map_len);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 205/321 nvmet-rdma: fix possible bad dereference when freeing rsps
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sagi Grimberg <[email protected]>
[ Upstream commit 73964c1d07c054376f1b32a62548571795159148 ]
It is possible that the host connected and saw a cm established event and started sending nvme capsules on the qp, however the ctrl did not yet see an established event. This is why the rsp_wait_list exists (for async handling of these cmds, we move them to a pending list).
Furthermore, it is possible that the ctrl cm times out, resulting in a connect-error cm event. in this case we hit a bad deref [1] because in nvmet_rdma_free_rsps we assume that all the responses are in the free list.
We are freeing the cmds array anyways, so don't even bother to remove the rsp from the free_list. It is also guaranteed that we are not racing anything when we are releasing the queue so no other context accessing this array should be running.
[1]:
--
Workqueue: nvmet-free-wq nvmet_rdma_free_queue_work [nvmet_rdma] [...] pc : nvmet_rdma_free_rsps+0x78/0xb8 [nvmet_rdma] lr : nvmet_rdma_free_queue_work+0x88/0x120 [nvmet_rdma] Call trace: nvmet_rdma_free_rsps+0x78/0xb8 [nvmet_rdma] nvmet_rdma_free_queue_work+0x88/0x120 [nvmet_rdma] process_one_work+0x1ec/0x4a0 worker_thread+0x48/0x490 kthread+0x158/0x160 ret_from_fork+0x10/0x18
--
--- drivers/nvme/target/rdma.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-)
drivers/nvme/target/rdma.c +4 -12
@@ -473,12 +473,8 @@ nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue)return 0 ; out_free: -while (--i >=0 ) { -struct nvmet_rdma_rsp *rsp = &queue->rsps[i]; - -list_del (&rsp->free_list); -nvmet_rdma_free_rsp (ndev, rsp); - } +while (--i >=0 ) +nvmet_rdma_free_rsp (ndev, &queue->rsps[i]);kfree (queue->rsps); out:return ret;
@@ -489,12 +485,8 @@ static void nvmet_rdma_free_rsps(struct nvmet_rdma_queue *queue)struct nvmet_rdma_device *ndev = queue->dev;int i, nr_rsps = queue->recv_queue_size *2 ; -for (i =0 ; i < nr_rsps; i++) { -struct nvmet_rdma_rsp *rsp = &queue->rsps[i]; - -list_del (&rsp->free_list); -nvmet_rdma_free_rsp (ndev, rsp); - } +for (i =0 ; i < nr_rsps; i++) +nvmet_rdma_free_rsp (ndev, &queue->rsps[i]);kfree (queue->rsps); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 206/321 drm/amdgpu: fix dereference null return value for the function amdgpu_vm_pt_parent
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jesse Zhang <[email protected]>
[ Upstream commit 511a623fb46a6cf578c61d4f2755783c48807c77 ]
The pointer parent may be NULLed by the function amdgpu_vm_pt_parent. To make the code more robust, check the pointer parent.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c +5 -1
@@ -754,11 +754,15 @@ int amdgpu_vm_pde_update(struct amdgpu_vm_update_params *params, struct amdgpu_vm_bo_base *entry) {struct amdgpu_vm_bo_base *parent =amdgpu_vm_pt_parent (entry); -struct amdgpu_bo *bo = parent->bo, *pbo; +struct amdgpu_bo *bo, *pbo;struct amdgpu_vm *vm = params->vm;uint64_t pde, pt, flags;unsigned int level; +if (WARN_ON (!parent)) +return -EINVAL ; + + bo = parent->bo;for (level =0 , pbo = bo->parent; pbo; ++level) pbo = pbo->parent;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 207/321 hrtimer: Prevent queuing of hrtimer without a function callback
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Chang <[email protected]>
[ Upstream commit 5a830bbce3af16833fe0092dec47b6dd30279825 ]
The hrtimer function callback must not be NULL. It has to be specified by the call side but it is not validated by the hrtimer code. When a hrtimer is queued without a function callback, the kernel crashes with a null pointer dereference when trying to execute the callback in __run_hrtimer().
Introduce a validation before queuing the hrtimer in hrtimer_start_range_ns().
[anna-maria: Rephrase commit message]
--- kernel/time/hrtimer.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/time/hrtimer.c +2 -0
@@ -1285,6 +1285,8 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,struct hrtimer_clock_base *base;unsigned long flags; +if (WARN_ON_ONCE (!timer->function)) +return ;/* * Check whether the HRTIMER_MODE_SOFT bit and hrtimer.is_soft * match on CONFIG_PREEMPT_RT = n. With PREEMPT_RT check the hard
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 208/321 gtp: pull network headers in gtp_dev_xmit()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 3a3be7ff9224f424e485287b54be00d2c6bd9c40 upstream.
syzbot/KMSAN reported use of uninit-value in get_dev_xmit() [1]
We must make sure the IPv4 or Ipv6 header is pulled in skb->head before accessing fields in them.
Use pskb_inet_may_pull() to fix this issue.
[1]
BUG: KMSAN: uninit-value in ipv6_pdp_find drivers/net/gtp.c:220 [inline] BUG: KMSAN: uninit-value in gtp_build_skb_ip6 drivers/net/gtp.c:1229 [inline] BUG: KMSAN: uninit-value in gtp_dev_xmit+0x1424/0x2540 drivers/net/gtp.c:1281 ipv6_pdp_find drivers/net/gtp.c:220 [inline] gtp_build_skb_ip6 drivers/net/gtp.c:1229 [inline] gtp_dev_xmit+0x1424/0x2540 drivers/net/gtp.c:1281 __netdev_start_xmit include/linux/netdevice.h:4913 [inline] netdev_start_xmit include/linux/netdevice.h:4922 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x247/0xa20 net/core/dev.c:3596 __dev_queue_xmit+0x358c/0x5610 net/core/dev.c:4423 dev_queue_xmit include/linux/netdevice.h:3105 [inline] packet_xmit+0x9c/0x6c0 net/packet/af_packet.c:276 packet_snd net/packet/af_packet.c:3145 [inline] packet_sendmsg+0x90e3/0xa3a0 net/packet/af_packet.c:3177 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x30f/0x380 net/socket.c:745 __sys_sendto+0x685/0x830 net/socket.c:2204 __do_sys_sendto net/socket.c:2216 [inline] __se_sys_sendto net/socket.c:2212 [inline] __x64_sys_sendto+0x125/0x1d0 net/socket.c:2212 x64_sys_call+0x3799/0x3c10 arch/x86/include/generated/asm/syscalls_64.h:45 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f
Uninit was created at:
slab_post_alloc_hook mm/slub.c:3994 [inline] slab_alloc_node mm/slub.c:4037 [inline] kmem_cache_alloc_node_noprof+0x6bf/0xb80 mm/slub.c:4080 kmalloc_reserve+0x13d/0x4a0 net/core/skbuff.c:583 __alloc_skb+0x363/0x7b0 net/core/skbuff.c:674 alloc_skb include/linux/skbuff.h:1320 [inline] alloc_skb_with_frags+0xc8/0xbf0 net/core/skbuff.c:6526 sock_alloc_send_pskb+0xa81/0xbf0 net/core/sock.c:2815 packet_alloc_skb net/packet/af_packet.c:2994 [inline] packet_snd net/packet/af_packet.c:3088 [inline] packet_sendmsg+0x749c/0xa3a0 net/packet/af_packet.c:3177 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x30f/0x380 net/socket.c:745 __sys_sendto+0x685/0x830 net/socket.c:2204 __do_sys_sendto net/socket.c:2216 [inline] __se_sys_sendto net/socket.c:2212 [inline] __x64_sys_sendto+0x125/0x1d0 net/socket.c:2212 x64_sys_call+0x3799/0x3c10 arch/x86/include/generated/asm/syscalls_64.h:45 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f CPU: 0 UID: 0 PID: 7115 Comm: syz.1.515 Not tainted 6.11.0-rc1-syzkaller-00043-g94ede2a3e913 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/27/2024
--- drivers/net/gtp.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/gtp.c +3 -0
@@ -900,6 +900,9 @@ static netdev_tx_t gtp_dev_xmit(struct sif (skb_cow_head (skb, dev->needed_headroom)) goto tx_err; +if (!pskb_inet_may_pull (skb)) + goto tx_err; +skb_reset_inner_headers (skb);/* PDP context lookups in gtp_build_skb_*() need rcu read-side lock. */
Greg Kroah-Hartman
maintainerPATCH 209/321 media: solo6x10: replace max(a, min(b, c)) by clamp(b, a, c)
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aurelien Jarno <[email protected]>
commit 31e97d7c9ae3de072d7b424b2cf706a03ec10720 upstream.
This patch replaces max(a, min(b, c)) by clamp(b, a, c) in the solo6x10 driver. This improves the readability and more importantly, for the solo6x10-p2m.c file, this reduces on my system (x86-64, gcc 13):
- the preprocessed size from 121 MiB to 4.5 MiB;
- the build CPU time from 46.8 s to 1.6 s;
- the build memory from 2786 MiB to 98MiB.
In fine, this allows this relatively simple C file to be built on a 32-bit system.
--- drivers/media/pci/solo6x10/solo6x10-offsets.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/media/pci/solo6x10/solo6x10-offsets.h +5 -5
@@ -57,16 +57,16 @@#define SOLO_MP4E_EXT_ADDR (__solo) \ (SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))#define SOLO_MP4E_EXT_SIZE (__solo) \ - max((__solo->nr_chans * 0x00080000), \ - min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) - \ - __SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000)) + clamp(__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo) - \ + __SOLO_JPEG_MIN_SIZE(__solo), \ + __solo->nr_chans * 0x00080000, 0x00ff0000)#define __SOLO_JPEG_MIN_SIZE (__solo) (__solo->nr_chans * 0x00080000)#define SOLO_JPEG_EXT_ADDR (__solo) \ (SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))#define SOLO_JPEG_EXT_SIZE (__solo) \ - max(__SOLO_JPEG_MIN_SIZE(__solo), \ - min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000)) + clamp(__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo), \ + __SOLO_JPEG_MIN_SIZE(__solo), 0x00ff0000)#define SOLO_SDRAM_END (__solo) \ (SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
Greg Kroah-Hartman
maintainerPATCH 210/321 i2c: tegra: allow DVC support to be compiled out
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michał Mirosław <[email protected]>
[ Upstream commit a55efa7edf37dc428da7058b25c58a54dc9db4e4 ]
Save a bit of code for newer Tegra platforms by compiling out DVC's I2C mode support that's used only for Tegra2.
$ size i2c-tegra.o
text data bss dec hex filename
- 11381 292 8 11681 2da1 i2c-tegra.o
+ 10193 292 8 10493 28fd i2c-tegra.oStable-dep-of: 14d069d92951 ("i2c: tegra: Do not mark ACPI devices as irq safe")
--- drivers/i2c/busses/i2c-tegra.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
drivers/i2c/busses/i2c-tegra.c +11 -6
@@ -298,6 +298,8 @@ struct tegra_i2c_dev {bool is_vi; }; +#define IS_DVC (dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc) +static void dvc_writel (struct tegra_i2c_dev *i2c_dev,u32 val,unsigned int reg) {
@@ -315,7 +317,7 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)*/ static u32 tegra_i2c_reg_addr (struct tegra_i2c_dev *i2c_dev,unsigned int reg) { -if (i2c_dev->is_dvc) +if (IS_DVC (i2c_dev)) reg += (reg >=I2C_TX_FIFO ) ?0x10 :0x40 ;else if (i2c_dev->is_vi) reg =0xc00 + (reg <<2 );
@@ -639,7 +641,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)WARN_ON_ONCE (err); -if (i2c_dev->is_dvc) +if (IS_DVC (i2c_dev))tegra_dvc_init (i2c_dev); val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
@@ -703,7 +705,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)return err; } -if (!i2c_dev->is_dvc && !i2c_dev->is_vi) { +if (!IS_DVC (i2c_dev) && !i2c_dev->is_vi) {u32 sl_cfg =i2c_readl (i2c_dev,I2C_SL_CNFG ); sl_cfg |=I2C_SL_CNFG_NACK |I2C_SL_CNFG_NEWSL ;
@@ -933,7 +935,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) }i2c_writel (i2c_dev, status,I2C_INT_STATUS ); -if (i2c_dev->is_dvc) +if (IS_DVC (i2c_dev))dvc_writel (i2c_dev,DVC_STATUS_I2C_DONE_INTR ,DVC_STATUS );/*
@@ -972,7 +974,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)i2c_writel (i2c_dev, status,I2C_INT_STATUS ); -if (i2c_dev->is_dvc) +if (IS_DVC (i2c_dev))dvc_writel (i2c_dev,DVC_STATUS_I2C_DONE_INTR ,DVC_STATUS );if (i2c_dev->dma_mode) {
@@ -1660,7 +1662,9 @@ static const struct of_device_id tegra_i2c_of_match[] = { { .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, }, { .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, }, { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, }, +#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) { .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, }, +#endif {}, }; MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
@@ -1675,7 +1679,8 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) multi_mode =device_property_read_bool (i2c_dev->dev,"multi-master" ); i2c_dev->multimaster_mode = multi_mode; -if (of_device_is_compatible (np,"nvidia,tegra20-i2c-dvc" )) +if (IS_ENABLED (CONFIG_ARCH_TEGRA_2x_SOC) && +of_device_is_compatible (np,"nvidia,tegra20-i2c-dvc" )) i2c_dev->is_dvc = true;if (of_device_is_compatible (np,"nvidia,tegra210-i2c-vi" ))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 211/321 i2c: tegra: allow VI support to be compiled out
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michał Mirosław <[email protected]>
[ Upstream commit 4f5d68c8591498c3955dc0228ed6606c1b138278 ]
Save a bit of code for older Tegra platforms by compiling out VI's I2C mode support that's used only for Tegra210.
$ size i2c-tegra.o text data bss dec hex filename 11381 292 8 11681 2da1 i2c-tegra.o (full) 10193 292 8 10493 28fd i2c-tegra.o (no-dvc) 9145 292 8 9445 24e5 i2c-tegra.o (no-vi,no-dvc)
Stable-dep-of: 14d069d92951 ("i2c: tegra: Do not mark ACPI devices as irq safe")
--- drivers/i2c/busses/i2c-tegra.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-)
drivers/i2c/busses/i2c-tegra.c +14 -10
@@ -299,6 +299,7 @@ struct tegra_i2c_dev { };#define IS_DVC (dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc) +#define IS_VI (dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && (dev)->is_vi)static void dvc_writel (struct tegra_i2c_dev *i2c_dev,u32 val,unsigned int reg)
@@ -319,7 +320,7 @@ static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg) {if (IS_DVC (i2c_dev)) reg += (reg >=I2C_TX_FIFO ) ?0x10 :0x40 ; -else if (i2c_dev->is_vi) +else if (IS_VI (i2c_dev)) reg =0xc00 + (reg <<2 );return reg;
@@ -332,7 +333,7 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)/* read back register to make sure that register writes completed */ if (reg !=I2C_TX_FIFO )readl_relaxed (i2c_dev->base +tegra_i2c_reg_addr (i2c_dev, reg)); -else if (i2c_dev->is_vi) +else if (IS_VI (i2c_dev))readl_relaxed (i2c_dev->base +tegra_i2c_reg_addr (i2c_dev,I2C_INT_STATUS )); }
@@ -448,7 +449,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)u32 *dma_buf;int err; -if (i2c_dev->is_vi) +if (IS_VI (i2c_dev))return 0 ;if (i2c_dev->hw->has_apb_dma) {
@@ -653,7 +654,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)i2c_writel (i2c_dev, val,I2C_CNFG );i2c_writel (i2c_dev,0 ,I2C_INT_MASK ); -if (i2c_dev->is_vi) +if (IS_VI (i2c_dev))tegra_i2c_vi_init (i2c_dev);switch (t->bus_freq_hz) {
@@ -705,7 +706,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)return err; } -if (!IS_DVC (i2c_dev) && !i2c_dev->is_vi) { +if (!IS_DVC (i2c_dev) && !IS_VI (i2c_dev)) {u32 sl_cfg =i2c_readl (i2c_dev,I2C_SL_CNFG ); sl_cfg |=I2C_SL_CNFG_NACK |I2C_SL_CNFG_NEWSL ;
@@ -848,7 +849,7 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) i2c_dev->msg_buf_remaining = buf_remaining; i2c_dev->msg_buf = buf + words_to_transfer *BYTES_PER_FIFO_WORD ; -if (i2c_dev->is_vi) +if (IS_VI (i2c_dev))i2c_writesl_vi (i2c_dev, buf,I2C_TX_FIFO , words_to_transfer);else i2c_writesl (i2c_dev, buf,I2C_TX_FIFO , words_to_transfer);
@@ -1656,7 +1657,9 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {static const struct of_device_id tegra_i2c_of_match[] = { { .compatible ="nvidia,tegra194-i2c" , .data = &tegra194_i2c_hw, }, { .compatible ="nvidia,tegra186-i2c" , .data = &tegra186_i2c_hw, }, +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) { .compatible ="nvidia,tegra210-i2c-vi" , .data = &tegra210_i2c_hw, }, +#endif { .compatible ="nvidia,tegra210-i2c" , .data = &tegra210_i2c_hw, }, { .compatible ="nvidia,tegra124-i2c" , .data = &tegra124_i2c_hw, }, { .compatible ="nvidia,tegra114-i2c" , .data = &tegra114_i2c_hw, },
@@ -1683,7 +1686,8 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) i2c_dev->is_dvc = true; -if (of_device_is_compatible (np,"nvidia,tegra210-i2c-vi" )) +if (IS_ENABLED (CONFIG_ARCH_TEGRA_210_SOC ) && +of_device_is_compatible (np,"nvidia,tegra210-i2c-vi" )) i2c_dev->is_vi = true; }
@@ -1712,7 +1716,7 @@ static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw) i2c_dev->clocks[i2c_dev->nclocks++].id ="fast-clk" ; -if (i2c_dev->is_vi) +if (IS_VI (i2c_dev)) i2c_dev->clocks[i2c_dev->nclocks++].id ="slow" ; err = devm_clk_bulk_get(i2c_dev->dev, i2c_dev->nclocks,
@@ -1830,7 +1834,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)* VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't * be used for atomic transfers. */ -if (!i2c_dev->is_vi) +if (!IS_VI (i2c_dev))pm_runtime_irq_safe (i2c_dev->dev);pm_runtime_enable (i2c_dev->dev);
@@ -1903,7 +1907,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)* power ON/OFF during runtime PM resume/suspend, meaning that * controller needs to be re-initialized after power ON. */ -if (i2c_dev->is_vi) { +if (IS_VI (i2c_dev)) { err =tegra_i2c_init (i2c_dev);if (err) goto disable_clocks;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 212/321 i2c: tegra: Do not mark ACPI devices as irq safe
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 14d069d92951a3e150c0a81f2ca3b93e54da913b ]
On ACPI machines, the tegra i2c module encounters an issue due to a mutex being called inside a spinlock. This leads to the following bug:
BUG: sleeping function called from invalid context at kernel/locking/mutex.c:585 ... Call trace: __might_sleep __mutex_lock_common mutex_lock_nested acpi_subsys_runtime_resume rpm_resume tegra_i2c_xfer
The problem arises because during __pm_runtime_resume(), the spinlock &dev->power.lock is acquired before rpm_resume() is called. Later, rpm_resume() invokes acpi_subsys_runtime_resume(), which relies on mutexes, triggering the error.
To address this issue, devices on ACPI are now marked as not IRQ-safe, considering the dependency of acpi_subsys_runtime_resume() on mutexes.
--- drivers/i2c/busses/i2c-tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-tegra.c +2 -2
@@ -1832,9 +1832,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)* domain. * * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't -* be used for atomic transfers. +* be used for atomic transfers. ACPI device is not IRQ safe also. */ -if (!IS_VI (i2c_dev)) +if (!IS_VI (i2c_dev) && !has_acpi_companion (i2c_dev->dev))pm_runtime_irq_safe (i2c_dev->dev);pm_runtime_enable (i2c_dev->dev);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 213/321 dm suspend: return -ERESTARTSYS instead of -EINTR
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
[ Upstream commit 1e1fd567d32fcf7544c6e09e0e5bc6c650da6e23 ]
This commit changes device mapper, so that it returns -ERESTARTSYS instead of -EINTR when it is interrupted by a signal (so that the ioctl can be restarted).
The manpage signal(7) says that the ioctl function should be restarted if the signal was handled with SA_RESTART.
--- drivers/md/dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/dm.c +2 -2
@@ -2511,7 +2511,7 @@ static int dm_wait_for_bios_completion(struct mapped_device *md, unsigned int tabreak ;if (signal_pending_state (task_state, current)) { - r = -EINTR ; + r = -ERESTARTSYS ;break ; }
@@ -2536,7 +2536,7 @@ static int dm_wait_for_completion(struct mapped_device *md, unsigned int task_stbreak ;if (signal_pending_state (task_state, current)) { - r = -EINTR ; + r = -ERESTARTSYS ;break ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 214/321 net: mana: Fix doorbell out of order violation and avoid unnecessary doorbell rings
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Long Li <[email protected]>
[ Upstream commit 58a63729c957621f1990c3494c702711188ca347 ]
After napi_complete_done() is called when NAPI is polling in the current process context, another NAPI may be scheduled and start running in softirq on another CPU and may ring the doorbell before the current CPU does. When combined with unnecessary rings when there is no need to arm the CQ, it triggers error paths in the hardware.
This patch fixes this by calling napi_complete_done() after doorbell rings. It limits the number of unnecessary rings when there is no need to arm. MANA hardware specifies that there must be one doorbell ring every 8 CQ wraparounds. This driver guarantees one doorbell ring as soon as the number of consumed CQEs exceeds 4 CQ wraparounds. In practical workloads, the 4 CQ wraparounds proves to be big enough that it rarely exceeds this limit before all the napi weight is consumed.
To implement this, add a per-CQ counter cq->work_done_since_doorbell, and make sure the CQ is armed as soon as passing 4 wraparounds of the CQ.
--- drivers/net/ethernet/microsoft/mana/mana.h | 1 + drivers/net/ethernet/microsoft/mana/mana_en.c | 24 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-)
drivers/net/ethernet/microsoft/mana/mana.h +1 -0
@@ -262,6 +262,7 @@ struct mana_cq {/* NAPI data */ struct napi_struct napi;int work_done; +int work_done_since_doorbell;int budget; };
drivers/net/ethernet/microsoft/mana/mana_en.c +15 -9
@@ -1311,7 +1311,6 @@ static void mana_poll_rx_cq(struct mana_cq *cq)static int mana_cq_handler (void *context,struct gdma_queue *gdma_queue) {struct mana_cq *cq = context; -u8 arm_bit;int w;WARN_ON_ONCE (cq->gdma_cq != gdma_queue);
@@ -1322,16 +1321,23 @@ static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue)mana_poll_tx_cq (cq); w = cq->work_done; - -if (w < cq->budget && -napi_complete_done (&cq->napi, w)) { - arm_bit =SET_ARM_BIT ; - }else { - arm_bit =0 ; + cq->work_done_since_doorbell += w; + +if (w < cq->budget) { +mana_gd_ring_cq (gdma_queue,SET_ARM_BIT ); + cq->work_done_since_doorbell =0 ; +napi_complete_done (&cq->napi, w); + }else if (cq->work_done_since_doorbell > + cq->gdma_cq->queue_size /COMP_ENTRY_SIZE *4 ) { +/* MANA hardware requires at least one doorbell ring every 8 +* wraparounds of CQ even if there is no need to arm the CQ. +* This driver rings the doorbell as soon as we have exceeded +* 4 wraparounds. +*/ +mana_gd_ring_cq (gdma_queue,0 ); + cq->work_done_since_doorbell =0 ; } -mana_gd_ring_cq (gdma_queue, arm_bit); -return w; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 215/321 btrfs: replace sb::s_blocksize by fs_info::sectorsize
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit 4e00422ee62663e31e611d7de4d2c4aa3f8555f2 ]
The block size stored in the super block is used by subsystems outside of btrfs and it's a copy of fs_info::sectorsize. Unify that to always use our sectorsize, with the exception of mount where we first need to use fixed values (4K) until we read the super block and can set the sectorsize.
Replace all uses, in most cases it's fewer pointer indirections.
Stable-dep-of: 46a6e10a1ab1 ("btrfs: send: allow cloning non-aligned extent if it ends at i_size")
--- fs/btrfs/disk-io.c | 2 ++ fs/btrfs/extent_io.c | 4 ++-- fs/btrfs/inode.c | 2 +- fs/btrfs/ioctl.c | 2 +- fs/btrfs/reflink.c | 6 +++--- fs/btrfs/send.c | 2 +- fs/btrfs/super.c | 2 +- 7 files changed, 11 insertions(+), 9 deletions(-)
fs/btrfs/disk-io.c +2 -0
@@ -3130,6 +3130,7 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_blockint ret; fs_info->sb = sb; +/* Temporary fixed values for block size until we read the superblock. */ sb->s_blocksize =BTRFS_BDEV_BLOCKSIZE ; sb->s_blocksize_bits =blksize_bits (BTRFS_BDEV_BLOCKSIZE );
@@ -3628,6 +3629,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device sb->s_bdi->ra_pages *=btrfs_super_num_devices (disk_super); sb->s_bdi->ra_pages =max (sb->s_bdi->ra_pages,SZ_4M /PAGE_SIZE ); +/* Update the values for the current filesystem. */ sb->s_blocksize = sectorsize; sb->s_blocksize_bits =blksize_bits (sectorsize);memcpy (&sb->s_uuid, fs_info->fs_devices->fsid,BTRFS_FSID_SIZE );
fs/btrfs/extent_io.c +2 -2
@@ -1748,7 +1748,7 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,int ret =0 ;size_t pg_offset =0 ;size_t iosize; -size_t blocksize = inode->i_sb->s_blocksize; +size_t blocksize = fs_info->sectorsize;struct extent_io_tree *tree = &BTRFS_I (inode)->io_tree; ret =set_page_extent_mapped (page);
@@ -3348,7 +3348,7 @@ int extent_invalidate_folio(struct extent_io_tree *tree,struct extent_state *cached_state =NULL ;u64 start =folio_pos (folio);u64 end = start +folio_size (folio) -1 ; -size_t blocksize = folio->mapping->host->i_sb->s_blocksize; +size_t blocksize =btrfs_sb (folio->mapping->host->i_sb)->sectorsize;/* This function is only called for the btree inode */ ASSERT (tree->owner ==IO_TREE_BTREE_INODE_IO );
fs/btrfs/inode.c +1 -1
@@ -9111,7 +9111,7 @@ static int btrfs_getattr(struct user_namespace *mnt_userns,u64 delalloc_bytes;u64 inode_bytes;struct inode *inode =d_inode (path->dentry); -u32 blocksize = inode->i_sb->s_blocksize; +u32 blocksize =btrfs_sb (inode->i_sb)->sectorsize;u32 bi_flags =BTRFS_I (inode)->flags;u32 bi_ro_flags =BTRFS_I (inode)->ro_flags;
fs/btrfs/ioctl.c +1 -1
@@ -517,7 +517,7 @@ static noinline int btrfs_ioctl_fitrim(struct btrfs_fs_info *fs_info,* block group is in the logical address space, which can be any * sectorsize aligned bytenr in the range [0, U64_MAX]. */ -if (range.len < fs_info->sb->s_blocksize) +if (range.len < fs_info->sectorsize)return -EINVAL ; range.minlen =max (range.minlen, minlen);
fs/btrfs/reflink.c +3 -3
@@ -659,7 +659,7 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 len, struct inode *dst, u64 dst_loff) {struct btrfs_fs_info *fs_info =BTRFS_I (src)->root->fs_info; -const u64 bs = fs_info->sb->s_blocksize; +const u64 bs = fs_info->sectorsize;int ret;/*
@@ -726,7 +726,7 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,int ret;int wb_ret;u64 len = olen; -u64 bs = fs_info->sb->s_blocksize; +u64 bs = fs_info->sectorsize;/* * VFS's generic_remap_file_range_prep() protects us from cloning the
@@ -792,7 +792,7 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in, {struct inode *inode_in =file_inode (file_in);struct inode *inode_out =file_inode (file_out); -u64 bs =BTRFS_I (inode_out)->root->fs_info->sb->s_blocksize; +u64 bs =BTRFS_I (inode_out)->root->fs_info->sectorsize;u64 wb_len;int ret;
fs/btrfs/send.c +1 -1
@@ -5910,7 +5910,7 @@ static int send_write_or_clone(struct send_ctx *sctx,int ret =0 ;u64 offset = key->offset;u64 end; -u64 bs = sctx->send_root->fs_info->sb->s_blocksize; +u64 bs = sctx->send_root->fs_info->sectorsize; end =min_t (u64,btrfs_file_extent_end (path), sctx->cur_inode_size);if (offset >= end)
fs/btrfs/super.c +1 -1
@@ -2426,7 +2426,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bavail =0 ; buf->f_type =BTRFS_SUPER_MAGIC ; - buf->f_bsize = dentry->d_sb->s_blocksize; + buf->f_bsize = fs_info->sectorsize; buf->f_namelen =BTRFS_NAME_LEN ;/* We treat it as constant endianness (it doesn't matter _which_)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 216/321 btrfs: send: allow cloning non-aligned extent if it ends at i_size
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit 46a6e10a1ab16cc71d4a3cab73e79aabadd6b8ea ]
If we a find that an extent is shared but its end offset is not sector size aligned, then we don't clone it and issue write operations instead. This is because the reflink (remap_file_range) operation does not allow to clone unaligned ranges, except if the end offset of the range matches the i_size of the source and destination files (and the start offset is sector size aligned).
While this is not incorrect because send can only guarantee that a file has the same data in the source and destination snapshots, it's not optimal and generates confusion and surprising behaviour for users.
For example, running this test:
$ cat test.sh #!/bin/bash
DEV=/dev/sdi
MNT=/mnt/sdi
mkfs.btrfs -f $DEV
mount $DEV $MNT
# Use a file size not aligned to any possible sector size. file_size=$((1 * 1024 * 1024 + 5)) # 1MB + 5 bytes dd if=/dev/random of=$MNT/foo bs=$file_size count=1 cp --reflink=always $MNT/foo $MNT/bar
btrfs subvolume snapshot -r $MNT/ $MNT/snap
rm -f /tmp/send-test
btrfs send -f /tmp/send-test $MNT/snap
umount $MNT
mkfs.btrfs -f $DEV
mount $DEV $MNT
btrfs receive -vv -f /tmp/send-test $MNT
xfs_io -r -c "fiemap -v" $MNT/snap/bar
umount $MNT
Gives the following result:
(...)
mkfile o258-7-0
rename o258-7-0 -> bar
write bar - offset=0 length=49152
write bar - offset=49152 length=49152
write bar - offset=98304 length=49152
write bar - offset=147456 length=49152
write bar - offset=196608 length=49152
write bar - offset=245760 length=49152
write bar - offset=294912 length=49152
write bar - offset=344064 length=49152
write bar - offset=393216 length=49152
write bar - offset=442368 length=49152
write bar - offset=491520 length=49152
write bar - offset=540672 length=49152
write bar - offset=589824 length=49152
write bar - offset=638976 length=49152
write bar - offset=688128 length=49152
write bar - offset=737280 length=49152
write bar - offset=786432 length=49152
write bar - offset=835584 length=49152
write bar - offset=884736 length=49152
write bar - offset=933888 length=49152
write bar - offset=983040 length=49152
write bar - offset=1032192 length=16389
chown bar - uid=0, gid=0
chmod bar - mode=0644
utimes bar
utimes
BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=06d640da-9ca1-604c-b87c-3375175a8eb3, stransid=7 /mnt/sdi/snap/bar:
EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS
0: [0..2055]: 26624..28679 2056 0x1
There's no clone operation to clone extents from the file foo into file bar and fiemap confirms there's no shared flag (0x2000).
So update send_write_or_clone() so that it proceeds with cloning if the source and destination ranges end at the i_size of the respective files.
After this changes the result of the test is:
(...)
mkfile o258-7-0
rename o258-7-0 -> bar
clone bar - source=foo source offset=0 offset=0 length=1048581
chown bar - uid=0, gid=0
chmod bar - mode=0644
utimes bar
utimes
BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=582420f3-ea7d-564e-bbe5-ce440d622190, stransid=7 /mnt/sdi/snap/bar:
EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS
0: [0..2055]: 26624..28679 2056 0x2001
A test case for fstests will also follow up soon.
--- fs/btrfs/send.c | 52 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 13 deletions(-)
fs/btrfs/send.c +39 -13
@@ -5911,25 +5911,51 @@ static int send_write_or_clone(struct send_ctx *sctx,u64 offset = key->offset;u64 end;u64 bs = sctx->send_root->fs_info->sectorsize; +struct btrfs_file_extent_item *ei; +u64 disk_byte; +u64 data_offset; +u64 num_bytes; +struct btrfs_inode_info info = {0 }; end =min_t (u64,btrfs_file_extent_end (path), sctx->cur_inode_size);if (offset >= end)return 0 ; -if (clone_root &&IS_ALIGNED (end, bs)) { -struct btrfs_file_extent_item *ei; -u64 disk_byte; -u64 data_offset; + num_bytes = end - offset; - ei =btrfs_item_ptr (path->nodes[0 ], path->slots[0 ], - struct btrfs_file_extent_item); - disk_byte =btrfs_file_extent_disk_bytenr (path->nodes[0 ], ei); - data_offset =btrfs_file_extent_offset (path->nodes[0 ], ei); - ret =clone_range (sctx, path, clone_root, disk_byte, - data_offset, offset, end - offset); - }else { - ret =send_extent_data (sctx, path, offset, end - offset); - } +if (!clone_root) + goto write_data; + +if (IS_ALIGNED (end, bs)) + goto clone_data; + +/* +* If the extent end is not aligned, we can clone if the extent ends at +* the i_size of the inode and the clone range ends at the i_size of the +* source inode, otherwise the clone operation fails with -EINVAL. +*/ +if (end != sctx->cur_inode_size) + goto write_data; + + ret =get_inode_info (clone_root->root, clone_root->ino, &info); +if (ret <0 ) +return ret; + +if (clone_root->offset + num_bytes == info.size) + goto clone_data; + +write_data: + ret =send_extent_data (sctx, path, offset, num_bytes); + sctx->cur_inode_next_write_offset = end; +return ret; + +clone_data: + ei =btrfs_item_ptr (path->nodes[0 ], path->slots[0 ], + struct btrfs_file_extent_item); + disk_byte =btrfs_file_extent_disk_bytenr (path->nodes[0 ], ei); + data_offset =btrfs_file_extent_offset (path->nodes[0 ], ei); + ret =clone_range (sctx, path, clone_root, disk_byte, data_offset, offset, + num_bytes); sctx->cur_inode_next_write_offset = end;return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 217/321 drm/amd/display: Adjust cursor position
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rodrigo Siqueira <[email protected]>
[ Upstream commit 56fb276d0244d430496f249335a44ae114dd5f54 ]
[why & how]
When the commit 9d84c7ef8a87 ("drm/amd/display: Correct cursor position on horizontal mirror") was introduced, it used the wrong calculation for the position copy for X. This commit uses the correct calculation for that based on the original patch.
--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +1 -1
@@ -3633,7 +3633,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) (int)hubp->curs_attr.width || pos_cpy.x <= (int)hubp->curs_attr.width + pipe_ctx->plane_state->src_rect.x) { - pos_cpy.x =2 * viewport_width - temp_x; + pos_cpy.x = temp_x + viewport_width; } } }else {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 218/321 platform/surface: aggregator: Fix warning when controller is destroyed in probe
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maximilian Luz <[email protected]>
[ Upstream commit bc923d594db21bee0ead128eb4bb78f7e77467a4 ]
There is a small window in ssam_serial_hub_probe() where the controller is initialized but has not been started yet. Specifically, between ssam_controller_init() and ssam_controller_start(). Any failure in this window, for example caused by a failure of serdev_device_open(), currently results in an incorrect warning being emitted.
In particular, any failure in this window results in the controller being destroyed via ssam_controller_destroy(). This function checks the state of the controller and, in an attempt to validate that the controller has been cleanly shut down before we try and deallocate any resources, emits a warning if that state is not SSAM_CONTROLLER_STOPPED.
However, since we have only just initialized the controller and have not yet started it, its state is SSAM_CONTROLLER_INITIALIZED. Note that this is the only point at which the controller has this state, as it will change after we start the controller with ssam_controller_start() and never revert back. Further, at this point no communication has taken place and the sender and receiver threads have not been started yet (and we may not even have an open serdev device either).
Therefore, it is perfectly safe to call ssam_controller_destroy() with a state of SSAM_CONTROLLER_INITIALIZED. This, however, means that the warning currently being emitted is incorrect. Fix it by extending the check.
--- drivers/platform/surface/aggregator/controller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/platform/surface/aggregator/controller.c +2 -1
@@ -1354,7 +1354,8 @@ void ssam_controller_destroy(struct ssam_controller *ctrl)if (ctrl->state ==SSAM_CONTROLLER_UNINITIALIZED )return ; -WARN_ON (ctrl->state !=SSAM_CONTROLLER_STOPPED ); +WARN_ON (ctrl->state !=SSAM_CONTROLLER_STOPPED && + ctrl->state !=SSAM_CONTROLLER_INITIALIZED );/* * Note: New events could still have been received after the previous
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 219/321 drm/amdkfd: reserve the BO before validating it
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lang Yu <[email protected]>
[ Upstream commit 0c93bd49576677ae1a18817d5ec000ef031d5187 ]
Fix a warning.
v2: Avoid unmapping attachment repeatedly when ERESTARTSYS.
v3: Lock the BO before accessing ttm->sg to avoid race conditions.(Felix)
[ 41.708711] WARNING: CPU: 0 PID: 1463 at drivers/gpu/drm/ttm/ttm_bo.c:846 ttm_bo_validate+0x146/0x1b0 [ttm] [ 41.708989] Call Trace: [ 41.708992] <TASK> [ 41.708996] ? show_regs+0x6c/0x80 [ 41.709000] ? ttm_bo_validate+0x146/0x1b0 [ttm] [ 41.709008] ? __warn+0x93/0x190 [ 41.709014] ? ttm_bo_validate+0x146/0x1b0 [ttm] [ 41.709024] ? report_bug+0x1f9/0x210 [ 41.709035] ? handle_bug+0x46/0x80 [ 41.709041] ? exc_invalid_op+0x1d/0x80 [ 41.709048] ? asm_exc_invalid_op+0x1f/0x30 [ 41.709057] ? amdgpu_amdkfd_gpuvm_dmaunmap_mem+0x2c/0x80 [amdgpu] [ 41.709185] ? ttm_bo_validate+0x146/0x1b0 [ttm] [ 41.709197] ? amdgpu_amdkfd_gpuvm_dmaunmap_mem+0x2c/0x80 [amdgpu] [ 41.709337] ? srso_alias_return_thunk+0x5/0x7f [ 41.709346] kfd_mem_dmaunmap_attachment+0x9e/0x1e0 [amdgpu] [ 41.709467] amdgpu_amdkfd_gpuvm_dmaunmap_mem+0x56/0x80 [amdgpu] [ 41.709586] kfd_ioctl_unmap_memory_from_gpu+0x1b7/0x300 [amdgpu] [ 41.709710] kfd_ioctl+0x1ec/0x650 [amdgpu] [ 41.709822] ? __pfx_kfd_ioctl_unmap_memory_from_gpu+0x10/0x10 [amdgpu] [ 41.709945] ? srso_alias_return_thunk+0x5/0x7f [ 41.709949] ? tomoyo_file_ioctl+0x20/0x30 [ 41.709959] __x64_sys_ioctl+0x9c/0xd0 [ 41.709967] do_syscall_64+0x3f/0x90 [ 41.709973] entry_SYSCALL_64_after_hwframe+0x6e/0xd8
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 20 ++++++++++++++++--- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 4 +++- 3 files changed, 21 insertions(+), 5 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +1 -1
@@ -286,7 +286,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv);int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu (struct amdgpu_device *adev,struct kgd_mem *mem,void *drm_priv); -void amdgpu_amdkfd_gpuvm_dmaunmap_mem (struct kgd_mem *mem,void *drm_priv); +int amdgpu_amdkfd_gpuvm_dmaunmap_mem (struct kgd_mem *mem,void *drm_priv);int amdgpu_amdkfd_gpuvm_sync_memory (struct amdgpu_device *adev,struct kgd_mem *mem,bool intr); int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +17 -3
@@ -2025,21 +2025,35 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(return ret; } -void amdgpu_amdkfd_gpuvm_dmaunmap_mem (struct kgd_mem *mem,void *drm_priv) +int amdgpu_amdkfd_gpuvm_dmaunmap_mem (struct kgd_mem *mem,void *drm_priv) {struct kfd_mem_attachment *entry;struct amdgpu_vm *vm; +int ret; vm =drm_priv_to_vm (drm_priv);mutex_lock (&mem->lock); + ret =amdgpu_bo_reserve (mem->bo, true); +if (ret) + goto out; +list_for_each_entry (entry, &mem->attachments, list) { -if (entry->bo_va->base.vm == vm) -kfd_mem_dmaunmap_attachment (mem, entry); +if (entry->bo_va->base.vm != vm) +continue ; +if (entry->bo_va->base.bo->tbo.ttm && + !entry->bo_va->base.bo->tbo.ttm->sg) +continue ; + +kfd_mem_dmaunmap_attachment (mem, entry); } +amdgpu_bo_unreserve (mem->bo); +out:mutex_unlock (&mem->lock); + +return ret; } int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +3 -1
@@ -1410,7 +1410,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,kfd_flush_tlb (peer_pdd,TLB_FLUSH_HEAVYWEIGHT );/* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */ -amdgpu_amdkfd_gpuvm_dmaunmap_mem (mem, peer_pdd->drm_priv); + err =amdgpu_amdkfd_gpuvm_dmaunmap_mem (mem, peer_pdd->drm_priv); +if (err) + goto sync_memory_failed; }mutex_unlock (&p->mutex);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 220/321 Bluetooth: hci_core: Fix LE quote calculation
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 932021a11805b9da4bd6abf66fe233cccd59fe0e ]
Function hci_sched_le needs to update the respective counter variable inplace other the likes of hci_quote_sent would attempt to use the possible outdated value of conn->{le_cnt,acl_cnt}.
--- net/bluetooth/hci_core.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
net/bluetooth/hci_core.c +7 -12
@@ -3744,19 +3744,19 @@ static void hci_sched_le(struct hci_dev *hdev) {struct hci_chan *chan;struct sk_buff *skb; -int quote, cnt, tmp; +int quote, *cnt, tmp;BT_DBG ("%s" , hdev->name);if (!hci_conn_num (hdev,LE_LINK ))return ; - cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; + cnt = hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt; -__check_timeout (hdev, cnt,LE_LINK ); +__check_timeout (hdev, *cnt,LE_LINK ); - tmp = cnt; -while (cnt && (chan =hci_chan_sent (hdev,LE_LINK , "e))) { + tmp = *cnt; +while (*cnt && (chan =hci_chan_sent (hdev,LE_LINK , "e))) {u32 priority = (skb_peek (&chan->data_q))->priority;while (quote-- && (skb =skb_peek (&chan->data_q))) { BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
@@ -3771,7 +3771,7 @@ static void hci_sched_le(struct hci_dev *hdev)hci_send_frame (hdev, skb); hdev->le_last_tx = jiffies; - cnt--; + (*cnt)--; chan->sent++; chan->conn->sent++;
@@ -3781,12 +3781,7 @@ static void hci_sched_le(struct hci_dev *hdev) } } -if (hdev->le_pkts) - hdev->le_cnt = cnt; -else - hdev->acl_cnt = cnt; - -if (cnt != tmp) +if (*cnt != tmp)hci_prio_recalculate (hdev,LE_LINK ); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 221/321 Bluetooth: SMP: Fix assumption of Central always being Initiator
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 28cd47f75185c4818b0fb1b46f2f02faaba96376 ]
SMP initiator role shall be considered the one that initiates the pairing procedure with SMP_CMD_PAIRING_REQ:
BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part H page 1557:
Figure 2.1: LE pairing phases
Note that by sending SMP_CMD_SECURITY_REQ it doesn't change the role to be Initiator.
--- net/bluetooth/smp.c | 144 ++++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 72 deletions(-)
net/bluetooth/smp.c +72 -72
@@ -913,7 +913,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,* Confirms and the responder Enters the passkey. */ if (smp->method ==OVERLAP ) { -if (hcon->role ==HCI_ROLE_MASTER ) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) smp->method =CFM_PASSKEY ;else smp->method =REQ_PASSKEY ;
@@ -963,7 +963,7 @@ static u8 smp_confirm(struct smp_chan *smp)smp_send_cmd (smp->conn,SMP_CMD_PAIRING_CONFIRM ,sizeof (cp), &cp); -if (conn->hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_CONFIRM );else SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RANDOM );
@@ -979,7 +979,8 @@ static u8 smp_random(struct smp_chan *smp)int ret;bt_dev_dbg (conn->hcon->hdev,"conn %p %s" , conn, - conn->hcon->out ?"initiator" :"responder" ); +test_bit (SMP_FLAG_INITIATOR , &smp->flags) ?"initiator" : +"responder" ); ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp, hcon->init_addr_type, &hcon->init_addr,
@@ -993,7 +994,7 @@ static u8 smp_random(struct smp_chan *smp)return SMP_CONFIRM_FAILED ; } -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {u8 stk[16 ];__le64 rand =0 ;__le16 ediv =0 ;
@@ -1250,14 +1251,15 @@ static void smp_distribute_keys(struct smp_chan *smp) rsp = (void *) &smp->prsp[1 ];/* The responder sends its keys first */ -if (hcon->out && (smp->remote_key_dist &KEY_DIST_MASK )) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags) && + (smp->remote_key_dist &KEY_DIST_MASK )) {smp_allow_key_dist (smp);return ; } req = (void *) &smp->preq[1 ]; -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { keydist = &rsp->init_key_dist; *keydist &= req->init_key_dist; }else {
@@ -1426,7 +1428,7 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])struct hci_conn *hcon = smp->conn->hcon;u8 *na, *nb, a[7 ], b[7 ]; -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { na = smp->prnd; nb = smp->rrnd; }else {
@@ -1454,7 +1456,7 @@ static void sc_dhkey_check(struct smp_chan *smp) a[6 ] = hcon->init_addr_type; b[6 ] = hcon->resp_addr_type; -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { local_addr = a; remote_addr = b;memcpy (io_cap, &smp->preq[1 ],3 );
@@ -1533,7 +1535,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)/* The round is only complete when the initiator * receives pairing random. */ -if (!hcon->out) { +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);if (smp->passkey_round ==20 )
@@ -1561,7 +1563,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RANDOM ); -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);return 0 ;
@@ -1572,7 +1574,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)case SMP_CMD_PUBLIC_KEY :default :/* Initiating device starts the round */ -if (!hcon->out) +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags))return 0 ; bt_dev_dbg(hdev, "Starting passkey round %u",
@@ -1617,7 +1619,7 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey) }/* Initiator sends DHKey check first */ -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {sc_dhkey_check (smp);SMP_ALLOW_CMD (smp,SMP_CMD_DHKEY_CHECK ); }else if (test_and_clear_bit (SMP_FLAG_DHKEY_PENDING , &smp->flags)) {
@@ -1740,7 +1742,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)struct smp_cmd_pairing rsp, *req = (void *) skb->data;struct l2cap_chan *chan = conn->smp;struct hci_dev *hdev = conn->hcon->hdev; -struct smp_chan *smp; +struct smp_chan *smp = chan->data;u8 key_size, auth, sec_level;int ret;
@@ -1749,16 +1751,14 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)if (skb->len <sizeof (*req))return SMP_INVALID_PARAMS ; -if (conn->hcon->role !=HCI_ROLE_SLAVE ) +if (smp &&test_bit (SMP_FLAG_INITIATOR , &smp->flags))return SMP_CMD_NOTSUPP ; -if (!chan->data) +if (!smp) { smp =smp_chan_create (conn); -else - smp = chan->data; - -if (!smp) -return SMP_UNSPECIFIED ; +if (!smp) +return SMP_UNSPECIFIED ; + }/* We didn't start the pairing, so match remote */ auth = req->auth_req &AUTH_REQ_MASK (hdev);
@@ -1940,7 +1940,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)if (skb->len <sizeof (*rsp))return SMP_INVALID_PARAMS ; -if (conn->hcon->role !=HCI_ROLE_MASTER ) +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags))return SMP_CMD_NOTSUPP ;skb_pull (skb,sizeof (*rsp));
@@ -2035,7 +2035,7 @@ static u8 sc_check_confirm(struct smp_chan *smp)if (smp->method ==REQ_PASSKEY || smp->method ==DSP_PASSKEY )return sc_passkey_round (smp,SMP_CMD_PAIRING_CONFIRM ); -if (conn->hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RANDOM );
@@ -2057,7 +2057,7 @@ static int fixup_sc_false_positive(struct smp_chan *smp)u8 auth;/* The issue is only observed when we're in responder role */ -if (hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))return SMP_UNSPECIFIED ;if (hci_dev_test_flag (hdev,HCI_SC_ONLY )) {
@@ -2093,7 +2093,8 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)struct hci_dev *hdev = hcon->hdev;bt_dev_dbg (hdev,"conn %p %s" , conn, - hcon->out ?"initiator" :"responder" ); +test_bit (SMP_FLAG_INITIATOR , &smp->flags) ?"initiator" : +"responder" );if (skb->len <sizeof (smp->pcnf))return SMP_INVALID_PARAMS ;
@@ -2115,7 +2116,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)return ret; } -if (conn->hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RANDOM );
@@ -2150,7 +2151,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)if (!test_bit (SMP_FLAG_SC , &smp->flags))return smp_random (smp); -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { pkax = smp->local_pk; pkbx = smp->remote_pk; na = smp->prnd;
@@ -2163,7 +2164,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) }if (smp->method ==REQ_OOB ) { -if (!hcon->out) +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags))smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);SMP_ALLOW_CMD (smp,SMP_CMD_DHKEY_CHECK );
@@ -2174,7 +2175,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)if (smp->method ==REQ_PASSKEY || smp->method ==DSP_PASSKEY )return sc_passkey_round (smp,SMP_CMD_PAIRING_RANDOM ); -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {u8 cfm[16 ]; err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
@@ -2215,7 +2216,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)return SMP_UNSPECIFIED ;if (smp->method ==REQ_OOB ) { -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {sc_dhkey_check (smp);SMP_ALLOW_CMD (smp,SMP_CMD_DHKEY_CHECK ); }
@@ -2289,10 +2290,27 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,return false; } +static void smp_send_pairing_req (struct smp_chan *smp,__u8 auth) +{ +struct smp_cmd_pairing cp; + +if (smp->conn->hcon->type ==ACL_LINK ) +build_bredr_pairing_cmd (smp, &cp,NULL ); +else +build_pairing_cmd (smp->conn, &cp,NULL , auth); + + smp->preq[0 ] =SMP_CMD_PAIRING_REQ ; +memcpy (&smp->preq[1 ], &cp,sizeof (cp)); + +smp_send_cmd (smp->conn,SMP_CMD_PAIRING_REQ ,sizeof (cp), &cp); +SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RSP ); + +set_bit (SMP_FLAG_INITIATOR , &smp->flags); +} +static u8 smp_cmd_security_req (struct l2cap_conn *conn,struct sk_buff *skb) {struct smp_cmd_security_req *rp = (void *) skb->data; -struct smp_cmd_pairing cp;struct hci_conn *hcon = conn->hcon;struct hci_dev *hdev = hcon->hdev;struct smp_chan *smp;
@@ -2341,16 +2359,20 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)skb_pull (skb,sizeof (*rp)); -memset (&cp,0 ,sizeof (cp)); -build_pairing_cmd (conn, &cp,NULL , auth); +smp_send_pairing_req (smp, auth); - smp->preq[0 ] =SMP_CMD_PAIRING_REQ ; -memcpy (&smp->preq[1 ], &cp,sizeof (cp)); +return 0 ; +} -smp_send_cmd (conn,SMP_CMD_PAIRING_REQ ,sizeof (cp), &cp); -SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RSP ); +static void smp_send_security_req (struct smp_chan *smp,__u8 auth) +{ +struct smp_cmd_security_req cp; -return 0 ; + cp.auth_req = auth; +smp_send_cmd (smp->conn,SMP_CMD_SECURITY_REQ ,sizeof (cp), &cp); +SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_REQ ); + +clear_bit (SMP_FLAG_INITIATOR , &smp->flags); }int smp_conn_security (struct hci_conn *hcon,__u8 sec_level)
@@ -2421,23 +2443,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) authreq |=SMP_AUTH_MITM ; } -if (hcon->role ==HCI_ROLE_MASTER ) { -struct smp_cmd_pairing cp; - -build_pairing_cmd (conn, &cp,NULL , authreq); - smp->preq[0 ] =SMP_CMD_PAIRING_REQ ; -memcpy (&smp->preq[1 ], &cp,sizeof (cp)); - -smp_send_cmd (conn,SMP_CMD_PAIRING_REQ ,sizeof (cp), &cp); -SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RSP ); - }else { -struct smp_cmd_security_req cp; - cp.auth_req = authreq; -smp_send_cmd (conn,SMP_CMD_SECURITY_REQ ,sizeof (cp), &cp); -SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_REQ ); - } +if (hcon->role ==HCI_ROLE_MASTER ) +smp_send_pairing_req (smp, authreq); +else +smp_send_security_req (smp, authreq); -set_bit (SMP_FLAG_INITIATOR , &smp->flags); ret =0 ; unlock:
@@ -2688,8 +2698,6 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)static u8 sc_select_method (struct smp_chan *smp) { -struct l2cap_conn *conn = smp->conn; -struct hci_conn *hcon = conn->hcon;struct smp_cmd_pairing *local, *remote;u8 local_mitm, remote_mitm, local_io, remote_io, method;
@@ -2702,7 +2710,7 @@ static u8 sc_select_method(struct smp_chan *smp)* the "struct smp_cmd_pairing" from them we need to skip the * first byte which contains the opcode. */ -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { local = (void *) &smp->preq[1 ]; remote = (void *) &smp->prsp[1 ]; }else {
@@ -2771,7 +2779,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)/* Non-initiating device sends its public key after receiving * the key from the initiating device. */ -if (!hcon->out) { +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { err =sc_send_public_key (smp);if (err)return err;
@@ -2833,7 +2841,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) }if (smp->method ==REQ_OOB ) { -if (hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);
@@ -2842,7 +2850,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)return 0 ; } -if (hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_CONFIRM );if (smp->method ==REQ_PASSKEY ) {
@@ -2857,7 +2865,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)/* The Initiating device waits for the non-initiating device to * send the confirm value. */ -if (conn->hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))return 0 ; err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
@@ -2891,7 +2899,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) a[6 ] = hcon->init_addr_type; b[6 ] = hcon->resp_addr_type; -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { local_addr = a; remote_addr = b;memcpy (io_cap, &smp->prsp[1 ],3 );
@@ -2916,7 +2924,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)if (crypto_memneq (check->e, e,16 ))return SMP_DHKEY_CHECK_FAILED ; -if (!hcon->out) { +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {if (test_bit (SMP_FLAG_WAIT_USER , &smp->flags)) {set_bit (SMP_FLAG_DHKEY_PENDING , &smp->flags);return 0 ;
@@ -2928,7 +2936,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)sc_add_ltk (smp); -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {hci_le_start_enc (hcon,0 ,0 , smp->tk, smp->enc_key_size); hcon->enc_key_size = smp->enc_key_size; }
@@ -3077,7 +3085,6 @@ static void bredr_pairing(struct l2cap_chan *chan)struct l2cap_conn *conn = chan->conn;struct hci_conn *hcon = conn->hcon;struct hci_dev *hdev = hcon->hdev; -struct smp_cmd_pairing req;struct smp_chan *smp;bt_dev_dbg (hdev,"chan %p" , chan);
@@ -3129,14 +3136,7 @@ static void bredr_pairing(struct l2cap_chan *chan)bt_dev_dbg (hdev,"starting SMP over BR/EDR" ); -/* Prepare and send the BR/EDR SMP Pairing Request */ -build_bredr_pairing_cmd (smp, &req,NULL ); - - smp->preq[0 ] =SMP_CMD_PAIRING_REQ ; -memcpy (&smp->preq[1 ], &req,sizeof (req)); - -smp_send_cmd (conn,SMP_CMD_PAIRING_REQ ,sizeof (req), &req); -SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RSP ); +smp_send_pairing_req (smp,0x00 ); }static void smp_resume_cb (struct l2cap_chan *chan)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 222/321 net: dsa: tag_ocelot: do not rely on skb_mac_header() for VLAN xmit
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit eabb1494c9f20362ae53a9991481a1523be4f4b7 ]
skb_mac_header() will no longer be available in the TX path when reverting commit 6d1ccff62780 ("net: reset mac header in dev_start_xmit()"). As preparation for that, let's use skb_vlan_eth_hdr() to get to the VLAN header instead, which assumes it's located at skb->data (assumption which holds true here).
Stable-dep-of: 67c3ca2c5cfe ("net: mscc: ocelot: use ocelot_xmit_get_vlan_info() also for FDMA and register injection")
--- net/dsa/tag_ocelot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/dsa/tag_ocelot.c +1 -1
@@ -22,7 +22,7 @@ static void ocelot_xmit_get_vlan_info(struct sk_buff *skb, struct dsa_port *dp,return ; } - hdr = (struct vlan_ethhdr *)skb_mac_header (skb); + hdr =skb_vlan_eth_hdr (skb);br_vlan_get_proto (br, &proto);if (ntohs (hdr->h_vlan_proto) == proto) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 223/321 net: dsa: tag_ocelot: call only the relevant portion of __skb_vlan_pop() on TX
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit 0bcf2e4aca6c29a07555b713f2fb461dc38d5977 ]
ocelot_xmit_get_vlan_info() calls __skb_vlan_pop() as the most appropriate helper I could find which strips away a VLAN header. That's all I need it to do, but __skb_vlan_pop() has more logic, which will become incompatible with the future revert of commit 6d1ccff62780 ("net: reset mac header in dev_start_xmit()").
Namely, it performs a sanity check on skb_mac_header(), which will stop being set after the above revert, so it will return an error instead of removing the VLAN tag.
ocelot_xmit_get_vlan_info() gets called in 2 circumstances:
(1) the port is under a VLAN-aware bridge and the bridge sends VLAN-tagged packets
(2) the port is under a VLAN-aware bridge and somebody else (an 8021q upper) sends VLAN-tagged packets (using a VID that isn't in the bridge vlan tables)
In case (1), there is actually no bug to defend against, because br_dev_xmit() calls skb_reset_mac_header() and things continue to work.
However, in case (2), illustrated using the commands below, it can be seen that our intervention is needed, since __skb_vlan_pop() complains:
$ ip link add br0 type bridge vlan_filtering 1 && ip link set br0 up $ ip link set $eth master br0 && ip link set $eth up $ ip link add link $eth name $eth.100 type vlan id 100 && ip link set $eth.100 up $ ip addr add 192.168.100.1/24 dev $eth.100
I could fend off the checks in __skb_vlan_pop() with some skb_mac_header_was_set() calls, but seeing how few callers of __skb_vlan_pop() there are from TX paths, that seems rather unproductive.
As an alternative solution, extract the bare minimum logic to strip a VLAN header, and move it to a new helper named vlan_remove_tag(), close to the definition of vlan_insert_tag(). Document it appropriately and make ocelot_xmit_get_vlan_info() call this smaller helper instead.
Seeing that it doesn't appear illegal to test skb->protocol in the TX path, I guess it would be a good for vlan_remove_tag() to also absorb the vlan_set_encap_proto() function call.
Stable-dep-of: 67c3ca2c5cfe ("net: mscc: ocelot: use ocelot_xmit_get_vlan_info() also for FDMA and register injection")
--- include/linux/if_vlan.h | 21 +++++++++++++++++++++ net/core/skbuff.c | 8 +------- net/dsa/tag_ocelot.c | 2 +- 3 files changed, 23 insertions(+), 8 deletions(-)
include/linux/if_vlan.h +21 -0
@@ -704,6 +704,27 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, skb->protocol =htons (ETH_P_802_2 ); } +/** +* vlan_remove_tag - remove outer VLAN tag from payload +* @skb: skbuff to remove tag from +* @vlan_tci: buffer to store value +* +* Expects the skb to contain a VLAN tag in the payload, and to have skb->data +* pointing at the MAC header. +* +* Returns a new pointer to skb->data, or NULL on failure to pull. +*/ +static inline void *vlan_remove_tag (struct sk_buff *skb,u16 *vlan_tci) +{ +struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data +ETH_HLEN ); + + *vlan_tci =ntohs (vhdr->h_vlan_TCI); + +memmove (skb->data +VLAN_HLEN , skb->data,2 *ETH_ALEN ); +vlan_set_encap_proto (skb, vhdr); +return __skb_pull (skb,VLAN_HLEN ); +} +/** * skb_vlan_tagged - check if skb is vlan tagged. * @skb: skbuff to query
net/core/skbuff.c +1 -7
@@ -5791,7 +5791,6 @@ EXPORT_SYMBOL(skb_ensure_writable);*/ int __skb_vlan_pop (struct sk_buff *skb,u16 *vlan_tci) { -struct vlan_hdr *vhdr;int offset = skb->data -skb_mac_header (skb);int err;
@@ -5807,13 +5806,8 @@ int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci)skb_postpull_rcsum (skb, skb->data + (2 *ETH_ALEN ),VLAN_HLEN ); - vhdr = (struct vlan_hdr *)(skb->data +ETH_HLEN ); - *vlan_tci =ntohs (vhdr->h_vlan_TCI); - -memmove (skb->data +VLAN_HLEN , skb->data,2 *ETH_ALEN ); -__skb_pull (skb,VLAN_HLEN ); +vlan_remove_tag (skb, vlan_tci); -vlan_set_encap_proto (skb, vhdr); skb->mac_header +=VLAN_HLEN ;if (skb_network_offset (skb) <ETH_HLEN )
net/dsa/tag_ocelot.c +1 -1
@@ -26,7 +26,7 @@ static void ocelot_xmit_get_vlan_info(struct sk_buff *skb, struct dsa_port *dp,br_vlan_get_proto (br, &proto);if (ntohs (hdr->h_vlan_proto) == proto) { -__skb_vlan_pop (skb, &tci); +vlan_remove_tag (skb, &tci); *vlan_tci = tci; }else {rcu_read_lock ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 224/321 net: mscc: ocelot: use ocelot_xmit_get_vlan_info() also for FDMA and register injection
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit 67c3ca2c5cfe6a50772514e3349b5e7b3b0fac03 ]
Problem description
-------------------
On an NXP LS1028A (felix DSA driver) with the following configuration:
- ocelot-8021q tagging protocol
- VLAN-aware bridge (with STP) spanning at least swp0 and swp1
- 8021q VLAN upper interfaces on swp0 and swp1: swp0.700, swp1.700
- ptp4l on swp0.700 and swp1.700
we see that the ptp4l instances do not see each other's traffic, and they all go to the grand master state due to the ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES condition.
Jumping to the conclusion for the impatient
-------------------------------------------
There is a zero-day bug in the ocelot switchdev driver in the way it handles VLAN-tagged packet injection. The correct logic already exists in the source code, in function ocelot_xmit_get_vlan_info() added by commit 5ca721c54d86 ("net: dsa: tag_ocelot: set the classified VLAN during xmit"). But it is used only for normal NPI-based injection with the DSA "ocelot" tagging protocol. The other injection code paths (register-based and FDMA-based) roll their own wrong logic. This affects and was noticed on the DSA "ocelot-8021q" protocol because it uses register-based injection.
By moving ocelot_xmit_get_vlan_info() to a place that's common for both the DSA tagger and the ocelot switch library, it can also be called from ocelot_port_inject_frame() in ocelot.c.
We need to touch the lines with ocelot_ifh_port_set()'s prototype anyway, so let's rename it to something clearer regarding what it does, and add a kernel-doc. ocelot_ifh_set_basic() should do.
Investigation notes
-------------------
Debugging reveals that PTP event (aka those carrying timestamps, like Sync) frames injected into swp0.700 (but also swp1.700) hit the wire with two VLAN tags:
00000000: 01 1b 19 00 00 00 00 01 02 03 04 05 81 00 02 bc
~~~~~~~~~~~
00000010: 81 00 02 bc 88 f7 00 12 00 2c 00 00 02 00 00 00
~~~~~~~~~~~00000020: 00 00 00 00 00 00 00 00 00 00 00 01 02 ff fe 03 00000030: 04 05 00 01 00 04 00 00 00 00 00 00 00 00 00 00 00000040: 00 00
The second (unexpected) VLAN tag makes felix_check_xtr_pkt() -> ptp_classify_raw() fail to see these as PTP packets at the link partner's receiving end, and return PTP_CLASS_NONE (because the BPF classifier is not written to expect 2 VLAN tags).
The reason why packets have 2 VLAN tags is because the transmission code treats VLAN incorrectly.
Neither ocelot switchdev, nor felix DSA, declare the NETIF_F_HW_VLAN_CTAG_TX feature. Therefore, at xmit time, all VLANs should be in the skb head, and none should be in the hwaccel area. This is done by:
static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
netdev_features_t features)
{
if (skb_vlan_tag_present(skb) &&
!vlan_hw_offload_capable(features, skb->vlan_proto))
skb = __vlan_hwaccel_push_inside(skb);
return skb;
}But ocelot_port_inject_frame() handles things incorrectly:
ocelot_ifh_port_set(ifh, port, rew_op, skb_vlan_tag_get(skb));
void ocelot_ifh_port_set(struct sk_buff *skb, void *ifh, int port, u32 rew_op)
{
(...)
if (vlan_tag)
ocelot_ifh_set_vlan_tci(ifh, vlan_tag);
(...)
}The way __vlan_hwaccel_push_inside() pushes the tag inside the skb head is by calling:
static inline void __vlan_hwaccel_clear_tag(struct sk_buff *skb)
{
skb->vlan_present = 0;
}which does _not_ zero out skb->vlan_tci as seen by skb_vlan_tag_get(). This means that ocelot, when it calls skb_vlan_tag_get(), sees (and uses) a residual skb->vlan_tci, while the same VLAN tag is _already_ in the skb head.
The trivial fix for double VLAN headers is to replace the content of ocelot_ifh_port_set() with:
if (skb_vlan_tag_present(skb)) ocelot_ifh_set_vlan_tci(ifh, skb_vlan_tag_get(skb));
but this would not be correct either, because, as mentioned, vlan_hw_offload_capable() is false for us, so we'd be inserting dead code and we'd always transmit packets with VID=0 in the injection frame header.
I can't actually test the ocelot switchdev driver and rely exclusively on code inspection, but I don't think traffic from 8021q uppers has ever been injected properly, and not double-tagged. Thus I'm blaming the introduction of VLAN fields in the injection header - early driver code.
As hinted at in the early conclusion, what we _want_ to happen for VLAN transmission was already described once in commit 5ca721c54d86 ("net: dsa: tag_ocelot: set the classified VLAN during xmit").
ocelot_xmit_get_vlan_info() intends to ensure that if the port through which we're transmitting is under a VLAN-aware bridge, the outer VLAN tag from the skb head is stripped from there and inserted into the injection frame header (so that the packet is processed in hardware through that actual VLAN). And in all other cases, the packet is sent with VID=0 in the injection frame header, since the port is VLAN-unaware and has logic to strip this VID on egress (making it invisible to the wire).
--- drivers/net/ethernet/mscc/ocelot.c | 29 +++++++++++---- drivers/net/ethernet/mscc/ocelot_fdma.c | 2 +- include/linux/dsa/ocelot.h | 47 +++++++++++++++++++++++++ include/soc/mscc/ocelot.h | 3 +- net/dsa/tag_ocelot.c | 37 ++----------------- 5 files changed, 75 insertions(+), 43 deletions(-)
drivers/net/ethernet/mscc/ocelot.c +23 -6
@@ -1088,17 +1088,34 @@ bool ocelot_can_inject(struct ocelot *ocelot, int grp) }EXPORT_SYMBOL (ocelot_can_inject); -void ocelot_ifh_port_set (void *ifh,int port,u32 rew_op,u32 vlan_tag) +/** +* ocelot_ifh_set_basic - Set basic information in Injection Frame Header +* @ifh: Pointer to Injection Frame Header memory +* @ocelot: Switch private data structure +* @port: Egress port number +* @rew_op: Egress rewriter operation for PTP +* @skb: Pointer to socket buffer (packet) +* +* Populate the Injection Frame Header with basic information for this skb: the +* analyzer bypass bit, destination port, VLAN info, egress rewriter info. +*/ +void ocelot_ifh_set_basic (void *ifh,struct ocelot *ocelot,int port, +u32 rew_op,struct sk_buff *skb) { +struct ocelot_port *ocelot_port = ocelot->ports[port]; +u64 vlan_tci, tag_type; + +ocelot_xmit_get_vlan_info (skb, ocelot_port->bridge, &vlan_tci, + &tag_type); +ocelot_ifh_set_bypass (ifh,1 );ocelot_ifh_set_dest (ifh,BIT_ULL (port)); -ocelot_ifh_set_tag_type (ifh,IFH_TAG_TYPE_C ); -if (vlan_tag) -ocelot_ifh_set_vlan_tci (ifh, vlan_tag); +ocelot_ifh_set_tag_type (ifh, tag_type); +ocelot_ifh_set_vlan_tci (ifh, vlan_tci);if (rew_op)ocelot_ifh_set_rew_op (ifh, rew_op); } -EXPORT_SYMBOL (ocelot_ifh_port_set); +EXPORT_SYMBOL (ocelot_ifh_set_basic);void ocelot_port_inject_frame (struct ocelot *ocelot,int port,int grp,u32 rew_op,struct sk_buff *skb)
@@ -1109,7 +1126,7 @@ void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp,ocelot_write_rix (ocelot,QS_INJ_CTRL_GAP_SIZE (1 ) |QS_INJ_CTRL_SOF ,QS_INJ_CTRL , grp); -ocelot_ifh_port_set (ifh, port, rew_op,skb_vlan_tag_get (skb)); +ocelot_ifh_set_basic (ifh, ocelot, port, rew_op, skb);for (i =0 ; i <OCELOT_TAG_LEN /4 ; i++)ocelot_write_rix (ocelot, ifh[i],QS_INJ_WR , grp);
drivers/net/ethernet/mscc/ocelot_fdma.c +1 -1
@@ -666,7 +666,7 @@ static int ocelot_fdma_prepare_skb(struct ocelot *ocelot, int port, u32 rew_op, ifh =skb_push (skb,OCELOT_TAG_LEN );skb_put (skb,ETH_FCS_LEN );memset (ifh,0 ,OCELOT_TAG_LEN ); -ocelot_ifh_port_set (ifh, port, rew_op,skb_vlan_tag_get (skb)); +ocelot_ifh_set_basic (ifh, ocelot, port, rew_op, skb);return 0 ; }
include/linux/dsa/ocelot.h +47 -0
57 lines not on this page · raw message
include/soc/mscc/ocelot.h +2 -1
@@ -1128,7 +1128,8 @@ void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,bool ocelot_can_inject (struct ocelot *ocelot,int grp);void ocelot_port_inject_frame (struct ocelot *ocelot,int port,int grp,u32 rew_op,struct sk_buff *skb); -void ocelot_ifh_port_set (void *ifh,int port,u32 rew_op,u32 vlan_tag); +void ocelot_ifh_set_basic (void *ifh,struct ocelot *ocelot,int port, +u32 rew_op,struct sk_buff *skb);int ocelot_xtr_poll_frame (struct ocelot *ocelot,int grp,struct sk_buff **skb);void ocelot_drain_cpu_queue (struct ocelot *ocelot,int grp); void ocelot_ptp_rx_timestamp(struct ocelot *ocelot, struct sk_buff *skb,
net/dsa/tag_ocelot.c +2 -35
@@ -4,40 +4,6 @@#include <linux/dsa/ocelot.h> #include "dsa_priv.h" -/* If the port is under a VLAN-aware bridge, remove the VLAN header from the -* payload and move it into the DSA tag, which will make the switch classify -* the packet to the bridge VLAN. Otherwise, leave the classified VLAN at zero, -* which is the pvid of standalone and VLAN-unaware bridge ports. -*/ -static void ocelot_xmit_get_vlan_info (struct sk_buff *skb,struct dsa_port *dp, -u64 *vlan_tci,u64 *tag_type) -{ -struct net_device *br =dsa_port_bridge_dev_get (dp); -struct vlan_ethhdr *hdr; -u16 proto, tci; - -if (!br || !br_vlan_enabled (br)) { - *vlan_tci =0 ; - *tag_type =IFH_TAG_TYPE_C ; -return ; - } - - hdr =skb_vlan_eth_hdr (skb); -br_vlan_get_proto (br, &proto); - -if (ntohs (hdr->h_vlan_proto) == proto) { -vlan_remove_tag (skb, &tci); - *vlan_tci = tci; - }else { -rcu_read_lock (); -br_vlan_get_pvid_rcu (br, &tci); -rcu_read_unlock (); - *vlan_tci = tci; - } - - *tag_type = (proto !=ETH_P_8021Q ) ?IFH_TAG_TYPE_S :IFH_TAG_TYPE_C ; -} -static void ocelot_xmit_common (struct sk_buff *skb,struct net_device *netdev,__be32 ifh_prefix,void **ifh) {
@@ -49,7 +15,8 @@ static void ocelot_xmit_common(struct sk_buff *skb, struct net_device *netdev,u32 rew_op =0 ;u64 qos_class; -ocelot_xmit_get_vlan_info (skb, dp, &vlan_tci, &tag_type); +ocelot_xmit_get_vlan_info (skb,dsa_port_bridge_dev_get (dp), &vlan_tci, + &tag_type); qos_class =netdev_get_num_tc (netdev) ?netdev_get_prio_tc_map (netdev, skb->priority) : skb->priority;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 225/321 net: mscc: ocelot: fix QoS class for injected packets with "ocelot-8021q"
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit e1b9e80236c540fa85d76e2d510d1b38e1968c5d ]
There are 2 distinct code paths (listed below) in the source code which set up an injection header for Ocelot(-like) switches. Code path (2) lacks the QoS class and source port being set correctly. Especially the improper QoS classification is a problem for the "ocelot-8021q" alternative DSA tagging protocol, because we support tc-taprio and each packet needs to be scheduled precisely through its time slot. This includes PTP, which is normally assigned to a traffic class other than 0, but would be sent through TC 0 nonetheless.
The code paths are:
(1) ocelot_xmit_common() from net/dsa/tag_ocelot.c - called only by the standard "ocelot" DSA tagging protocol which uses NPI-based injection - sets up bit fields in the tag manually to account for a small difference (destination port offset) between Ocelot and Seville. Namely, ocelot_ifh_set_dest() is omitted out of ocelot_xmit_common(), because there's also seville_ifh_set_dest().
(2) ocelot_ifh_set_basic(), called by:
- ocelot_fdma_prepare_skb() for FDMA transmission of the ocelot switchdev driver
- ocelot_port_xmit() -> ocelot_port_inject_frame() for register-based transmission of the ocelot switchdev driver
- felix_port_deferred_xmit() -> ocelot_port_inject_frame() for the DSA tagger ocelot-8021q when it must transmit PTP frames (also through register-based injection).
sets the bit fields according to its own logic.
The problem is that (2) doesn't call ocelot_ifh_set_qos_class(). Copying that logic from ocelot_xmit_common() fixes that.
Unfortunately, although desirable, it is not easily possible to de-duplicate code paths (1) and (2), and make net/dsa/tag_ocelot.c directly call ocelot_ifh_set_basic()), because of the ocelot/seville difference. This is the "minimal" fix with some logic duplicated (but at least more consolidated).
--- drivers/net/ethernet/mscc/ocelot.c | 10 +++++++++- drivers/net/ethernet/mscc/ocelot_fdma.c | 1 - 2 files changed, 9 insertions(+), 2 deletions(-)
drivers/net/ethernet/mscc/ocelot.c +9 -1
@@ -1103,13 +1103,21 @@ void ocelot_ifh_set_basic(void *ifh, struct ocelot *ocelot, int port, u32 rew_op, struct sk_buff *skb) { struct ocelot_port *ocelot_port = ocelot->ports[port]; +struct net_device *dev = skb->dev;u64 vlan_tci, tag_type; +int qos_class;ocelot_xmit_get_vlan_info (skb, ocelot_port->bridge, &vlan_tci, &tag_type); + qos_class =netdev_get_num_tc (dev) ? +netdev_get_prio_tc_map (dev, skb->priority) : skb->priority; + +memset (ifh,0 ,OCELOT_TAG_LEN );ocelot_ifh_set_bypass (ifh,1 ); +ocelot_ifh_set_src (ifh,BIT_ULL (ocelot->num_phys_ports));ocelot_ifh_set_dest (ifh,BIT_ULL (port)); +ocelot_ifh_set_qos_class (ifh, qos_class);ocelot_ifh_set_tag_type (ifh, tag_type);ocelot_ifh_set_vlan_tci (ifh, vlan_tci);if (rew_op)
@@ -1120,7 +1128,7 @@ EXPORT_SYMBOL(ocelot_ifh_set_basic);void ocelot_port_inject_frame (struct ocelot *ocelot,int port,int grp,u32 rew_op,struct sk_buff *skb) { -u32 ifh[OCELOT_TAG_LEN /4 ] = {0 }; +u32 ifh[OCELOT_TAG_LEN /4 ];unsigned int i, count, last; ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
drivers/net/ethernet/mscc/ocelot_fdma.c +0 -1
@@ -665,7 +665,6 @@ static int ocelot_fdma_prepare_skb(struct ocelot *ocelot, int port, u32 rew_op, ifh =skb_push (skb,OCELOT_TAG_LEN );skb_put (skb,ETH_FCS_LEN ); -memset (ifh,0 ,OCELOT_TAG_LEN );ocelot_ifh_set_basic (ifh, ocelot, port, rew_op, skb);return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 226/321 net: mscc: ocelot: serialize access to the injection/extraction groups
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit c5e12ac3beb0dd3a718296b2d8af5528e9ab728e ]
As explained by Horatiu Vultur in commit 603ead96582d ("net: sparx5: Add spinlock for frame transmission from CPU") which is for a similar hardware design, multiple CPUs can simultaneously perform injection or extraction. There are only 2 register groups for injection and 2 for extraction, and the driver only uses one of each. So we'd better serialize access using spin locks, otherwise frame corruption is possible.
Note that unlike in sparx5, FDMA in ocelot does not have this issue because struct ocelot_fdma_tx_ring already contains an xmit_lock.
I guess this is mostly a problem for NXP LS1028A, as that is dual core. I don't think VSC7514 is. So I'm blaming the commit where LS1028A (aka the felix DSA driver) started using register-based packet injection and extraction.
--- drivers/net/dsa/ocelot/felix.c | 11 +++++ drivers/net/ethernet/mscc/ocelot.c | 52 ++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 4 ++ include/soc/mscc/ocelot.h | 9 ++++ 4 files changed, 76 insertions(+)
drivers/net/dsa/ocelot/felix.c +11 -0
@@ -528,7 +528,9 @@ static int felix_tag_8021q_setup(struct dsa_switch *ds)* so we need to be careful that there are no extra frames to be * dequeued over MMIO, since we would never know to discard them. */ +ocelot_lock_xtr_grp_bh (ocelot,0 );ocelot_drain_cpu_queue (ocelot,0 ); +ocelot_unlock_xtr_grp_bh (ocelot,0 );return 0 ; }
@@ -1493,6 +1495,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)int port = xmit_work->dp->index;int retries =10 ; +ocelot_lock_inj_grp (ocelot,0 ); + do { if (ocelot_can_inject(ocelot, 0)) break;
@@ -1501,6 +1505,7 @@ static void felix_port_deferred_xmit(struct kthread_work *work) }while (--retries);if (!retries) { +ocelot_unlock_inj_grp (ocelot,0 );dev_err (ocelot->dev,"port %d failed to inject skb\n" , port);ocelot_port_purge_txtstamp_skb (ocelot, port, skb);
@@ -1510,6 +1515,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)ocelot_port_inject_frame (ocelot, port,0 , rew_op, skb); +ocelot_unlock_inj_grp (ocelot,0 ); +consume_skb (skb);kfree (xmit_work); }
@@ -1658,6 +1665,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)if (!felix->info->quirk_no_xtr_irq)return false; +ocelot_lock_xtr_grp (ocelot, grp); +while (ocelot_read (ocelot,QS_XTR_DATA_PRESENT ) &BIT (grp)) {struct sk_buff *skb;unsigned int type;
@@ -1694,6 +1703,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)ocelot_drain_cpu_queue (ocelot,0 ); } +ocelot_unlock_xtr_grp (ocelot, grp); +return true; }
drivers/net/ethernet/mscc/ocelot.c +52 -0
88 lines not on this page · raw message
drivers/net/ethernet/mscc/ocelot_vsc7514.c +4 -0
@@ -159,6 +159,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)struct ocelot *ocelot = arg;int grp =0 , err; +ocelot_lock_xtr_grp (ocelot, grp); +while (ocelot_read (ocelot,QS_XTR_DATA_PRESENT ) &BIT (grp)) {struct sk_buff *skb;
@@ -177,6 +179,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)if (err <0 )ocelot_drain_cpu_queue (ocelot,0 ); +ocelot_unlock_xtr_grp (ocelot, grp); +return IRQ_HANDLED ; }
include/soc/mscc/ocelot.h +9 -0
@@ -977,6 +977,9 @@ struct ocelot {const struct ocelot_stat_layout *stats_layout;struct list_head stats_regions; +spinlock_t inj_lock; +spinlock_t xtr_lock; +u32 pool_size[OCELOT_SB_NUM ][OCELOT_SB_POOL_NUM ];int packet_buffer_size;int num_frame_refs;
@@ -1125,6 +1128,12 @@ void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target, u32 val, u32 reg, u32 offset);/* Packet I/O */ +void ocelot_lock_inj_grp (struct ocelot *ocelot,int grp); +void ocelot_unlock_inj_grp (struct ocelot *ocelot,int grp); +void ocelot_lock_xtr_grp (struct ocelot *ocelot,int grp); +void ocelot_unlock_xtr_grp (struct ocelot *ocelot,int grp); +void ocelot_lock_xtr_grp_bh (struct ocelot *ocelot,int grp); +void ocelot_unlock_xtr_grp_bh (struct ocelot *ocelot,int grp);bool ocelot_can_inject (struct ocelot *ocelot,int grp);void ocelot_port_inject_frame (struct ocelot *ocelot,int port,int grp,u32 rew_op,struct sk_buff *skb);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 227/321 tc-testing: dont access non-existent variable on exception
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Horman <[email protected]>
[ Upstream commit a0c9fe5eecc97680323ee83780ea3eaf440ba1b7 ]
Since commit 255c1c7279ab ("tc-testing: Allow test cases to be skipped") the variable test_ordinal doesn't exist in call_pre_case(). So it should not be accessed when an exception occurs.
This resolves the following splat:
...
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ".../tdc.py", line 1028, in <module>
main()
File ".../tdc.py", line 1022, in main
set_operation_mode(pm, parser, args, remaining)
File ".../tdc.py", line 966, in set_operation_mode
catresults = test_runner_serial(pm, args, alltests)
File ".../tdc.py", line 642, in test_runner_serial
(index, tsr) = test_runner(pm, args, alltests)
File ".../tdc.py", line 536, in test_runner
res = run_one_test(pm, args, index, tidx)
File ".../tdc.py", line 419, in run_one_test
pm.call_pre_case(tidx)
File ".../tdc.py", line 146, in call_pre_case
print('test_ordinal is {}'.format(test_ordinal)) NameError: name 'test_ordinal' is not defined
--- tools/testing/selftests/tc-testing/tdc.py | 1 - 1 file changed, 1 deletion(-)
tools/testing/selftests/tc-testing/tdc.py +0 -1
@@ -129,7 +129,6 @@ class PluginMgr: except Exception as ee: print('exception {} in call to pre_case for {} plugin'. format(ee, pgn_inst.__class__)) - print('test_ordinal is {}'.format(test_ordinal)) print('testid is {}'.format(caseinfo['id'])) raise
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 228/321 selftests/net: synchronize udpgro tests tx and rx connection
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas Karpinski <[email protected]>
[ Upstream commit 3bdd9fd29cb0f136b307559a19c107210ad5c314 ]
The sockets used by udpgso_bench_tx aren't always ready when udpgso_bench_tx transmits packets. This issue is more prevalent in -rt kernels, but can occur in both. Replace the hacky sleep calls with a function that checks whether the ports in the namespace are ready for use.
Stable-dep-of: 7167395a4be7 ("selftests: udpgro: report error when receive failed")
--- tools/testing/selftests/net/net_helper.sh | 22 +++++++++++++++++++ tools/testing/selftests/net/udpgro.sh | 13 +++++------ tools/testing/selftests/net/udpgro_bench.sh | 5 +++-- tools/testing/selftests/net/udpgro_frglist.sh | 5 +++-- 4 files changed, 34 insertions(+), 11 deletions(-) create mode 100755 tools/testing/selftests/net/net_helper.sh
tools/testing/selftests/net/net_helper.sh new file +22 -0
@@ -0,0 +1,22 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Helper functions + +wait_local_port_listen() +{ + local listener_ns="${1}" + local port="${2}" + local protocol="${3}" + local port_hex + local i + + port_hex="$(printf "%04X" "${port}")" + for i in $(seq 10); do + if ip netns exec "${listener_ns}" cat /proc/net/"${protocol}"* | \ + grep -q "${port_hex}"; then + break + fi + sleep 0.1 + done +}
tools/testing/selftests/net/udpgro.sh +6 -7
@@ -3,6 +3,8 @@ # # Run a series of udpgro functional tests. +source net_helper.sh + readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" BPF_FILE="../bpf/xdp_dummy.bpf.o"
@@ -51,8 +53,7 @@ run_one() { echo "ok" || \ echo "failed" & - # Hack: let bg programs complete the startup - sleep 0.2 + wait_local_port_listen ${PEER_NS} 8000 udp ./udpgso_bench_tx ${tx_args} ret=$? wait $(jobs -p)
@@ -97,7 +98,7 @@ run_one_nat() { echo "ok" || \ echo "failed"& - sleep 0.1 + wait_local_port_listen "${PEER_NS}" 8000 udp ./udpgso_bench_tx ${tx_args} ret=$? kill -INT $pid
@@ -118,11 +119,9 @@ run_one_2sock() { echo "ok" || \ echo "failed" & - # Hack: let bg programs complete the startup - sleep 0.2 + wait_local_port_listen "${PEER_NS}" 12345 udp ./udpgso_bench_tx ${tx_args} -p 12345 - sleep 0.1 - # first UDP GSO socket should be closed at this point + wait_local_port_listen "${PEER_NS}" 8000 udp ./udpgso_bench_tx ${tx_args} ret=$? wait $(jobs -p)
tools/testing/selftests/net/udpgro_bench.sh +3 -2
@@ -3,6 +3,8 @@ # # Run a series of udpgro benchmarks +source net_helper.sh + readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" BPF_FILE="../bpf/xdp_dummy.bpf.o"
@@ -40,8 +42,7 @@ run_one() { ip netns exec "${PEER_NS}" ./udpgso_bench_rx ${rx_args} -r & ip netns exec "${PEER_NS}" ./udpgso_bench_rx -t ${rx_args} -r & - # Hack: let bg programs complete the startup - sleep 0.2 + wait_local_port_listen "${PEER_NS}" 8000 udp ./udpgso_bench_tx ${tx_args} }
tools/testing/selftests/net/udpgro_frglist.sh +3 -2
@@ -3,6 +3,8 @@ # # Run a series of udpgro benchmarks +source net_helper.sh + readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" BPF_FILE="../bpf/xdp_dummy.bpf.o"
@@ -45,8 +47,7 @@ run_one() { echo ${rx_args} ip netns exec "${PEER_NS}" ./udpgso_bench_rx ${rx_args} -r & - # Hack: let bg programs complete the startup - sleep 0.2 + wait_local_port_listen "${PEER_NS}" 8000 udp ./udpgso_bench_tx ${tx_args} }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 229/321 selftests: udpgro: report error when receive failed
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit 7167395a4be7930ecac6a33b4e54d7e3dd9ee209 ]
Currently, we only check the latest senders's exit code. If the receiver report failed, it is not recoreded. Fix it by checking the exit code of all the involved processes.
Before:
bad GRO lookup ok
multiple GRO socks ./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520
./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520
failed
$ echo $? 0
After:
bad GRO lookup ok
multiple GRO socks ./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520
./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520
failed
$ echo $? 1
--- tools/testing/selftests/net/udpgro.sh | 44 ++++++++++++++++----------- 1 file changed, 27 insertions(+), 17 deletions(-)
tools/testing/selftests/net/udpgro.sh +27 -17
@@ -46,17 +46,19 @@ run_one() { local -r all="$@" local -r tx_args=${all%rx*} local -r rx_args=${all#*rx} + local ret=0 cfg_veth - ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} && \ - echo "ok" || \ - echo "failed" & + ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} & + local PID1=$! wait_local_port_listen ${PEER_NS} 8000 udp ./udpgso_bench_tx ${tx_args} - ret=$? - wait $(jobs -p) + check_err $? + wait ${PID1} + check_err $? + [ "$ret" -eq 0 ] && echo "ok" || echo "failed" return $ret }
@@ -73,6 +75,7 @@ run_one_nat() { local -r all="$@" local -r tx_args=${all%rx*} local -r rx_args=${all#*rx} + local ret=0 if [[ ${tx_args} = *-4* ]]; then ipt_cmd=iptables
@@ -93,16 +96,17 @@ run_one_nat() { # ... so that GRO will match the UDP_GRO enabled socket, but packets # will land on the 'plain' one ip netns exec "${PEER_NS}" ./udpgso_bench_rx -G ${family} -b ${addr1} -n 0 & - pid=$! - ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} && \ - echo "ok" || \ - echo "failed"& + local PID1=$! + ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} & + local PID2=$! wait_local_port_listen "${PEER_NS}" 8000 udp ./udpgso_bench_tx ${tx_args} - ret=$? - kill -INT $pid - wait $(jobs -p) + check_err $? + kill -INT ${PID1} + wait ${PID2} + check_err $? + [ "$ret" -eq 0 ] && echo "ok" || echo "failed" return $ret }
@@ -111,20 +115,26 @@ run_one_2sock() { local -r all="$@" local -r tx_args=${all%rx*} local -r rx_args=${all#*rx} + local ret=0 cfg_veth ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} -p 12345 & - ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} && \ - echo "ok" || \ - echo "failed" & + local PID1=$! + ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} & + local PID2=$! wait_local_port_listen "${PEER_NS}" 12345 udp ./udpgso_bench_tx ${tx_args} -p 12345 + check_err $? wait_local_port_listen "${PEER_NS}" 8000 udp ./udpgso_bench_tx ${tx_args} - ret=$? - wait $(jobs -p) + check_err $? + wait ${PID1} + check_err $? + wait ${PID2} + check_err $? + [ "$ret" -eq 0 ] && echo "ok" || echo "failed" return $ret }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 230/321 tcp/dccp: bypass empty buckets in inet_twsk_purge()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 50e2907ef8bb52cf80ecde9eec5c4dac07177146 ]
TCP ehash table is often sparsely populated.
inet_twsk_purge() spends too much time calling cond_resched().
This patch can reduce time spent in inet_twsk_purge() by 20x.
Stable-dep-of: 565d121b6998 ("tcp: prevent concurrent execution of tcp_sk_exit_batch")
--- net/ipv4/inet_timewait_sock.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
net/ipv4/inet_timewait_sock.c +7 -2
@@ -284,12 +284,17 @@ EXPORT_SYMBOL_GPL(__inet_twsk_schedule);/* Remove all non full sockets (TIME_WAIT and NEW_SYN_RECV) for dead netns */ void inet_twsk_purge (struct inet_hashinfo *hashinfo,int family) { +struct inet_ehash_bucket *head = &hashinfo->ehash[0 ]; +unsigned int ehash_mask = hashinfo->ehash_mask;struct hlist_nulls_node *node;unsigned int slot;struct sock *sk; -for (slot =0 ; slot <= hashinfo->ehash_mask; slot++) { -struct inet_ehash_bucket *head = &hashinfo->ehash[slot]; +for (slot =0 ; slot <= ehash_mask; slot++, head++) { + +if (hlist_nulls_empty (&head->chain)) +continue ; + restart_rcu:cond_resched ();rcu_read_lock ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 231/321 tcp/dccp: do not care about families in inet_twsk_purge()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 1eeb5043573981f3a1278876515851b7f6b1df1b ]
We lost ability to unload ipv6 module a long time ago.
Instead of calling expensive inet_twsk_purge() twice, we can handle all families in one round.
Also remove an extra line added in my prior patch, per Kuniyuki Iwashima feedback.
Stable-dep-of: 565d121b6998 ("tcp: prevent concurrent execution of tcp_sk_exit_batch")
--- include/net/inet_timewait_sock.h | 2 +- include/net/tcp.h | 2 +- net/dccp/ipv4.c | 2 +- net/dccp/ipv6.c | 6 ------ net/ipv4/inet_timewait_sock.c | 9 +++------ net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/tcp_minisocks.c | 6 +++--- net/ipv6/tcp_ipv6.c | 6 ------ 8 files changed, 10 insertions(+), 25 deletions(-)
include/net/inet_timewait_sock.h +1 -1
@@ -114,7 +114,7 @@ static inline void inet_twsk_reschedule(struct inet_timewait_sock *tw, int timeovoid inet_twsk_deschedule_put (struct inet_timewait_sock *tw); -void inet_twsk_purge (struct inet_hashinfo *hashinfo,int family); +void inet_twsk_purge (struct inet_hashinfo *hashinfo);static inline struct net *twsk_net (const struct inet_timewait_sock *twsk)
include/net/tcp.h +1 -1
@@ -352,7 +352,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb);void tcp_rcv_space_adjust (struct sock *sk);int tcp_twsk_unique (struct sock *sk,struct sock *sktw,void *twp);void tcp_twsk_destructor (struct sock *sk); -void tcp_twsk_purge (struct list_head *net_exit_list,int family); +void tcp_twsk_purge (struct list_head *net_exit_list);ssize_t tcp_splice_read (struct socket *sk,loff_t *ppos,struct pipe_inode_info *pipe,size_t len,unsigned int flags);
net/dccp/ipv4.c +1 -1
@@ -1042,7 +1042,7 @@ static void __net_exit dccp_v4_exit_net(struct net *net) static void __net_exit dccp_v4_exit_batch(struct list_head *net_exit_list) { -inet_twsk_purge (&dccp_hashinfo,AF_INET ); +inet_twsk_purge (&dccp_hashinfo); }static struct pernet_operations dccp_v4_ops = {
net/dccp/ipv6.c +0 -6
@@ -1121,15 +1121,9 @@ static void __net_exit dccp_v6_exit_net(struct net *net)inet_ctl_sock_destroy (pn->v6_ctl_sk); } -static void __net_exit dccp_v6_exit_batch(struct list_head *net_exit_list) -{ -inet_twsk_purge (&dccp_hashinfo,AF_INET6 ); -} -static struct pernet_operations dccp_v6_ops = { .init = dccp_v6_init_net, .exit = dccp_v6_exit_net, - .exit_batch = dccp_v6_exit_batch, .id = &dccp_v6_pernet_id, .size =sizeof (struct dccp_v6_pernet ), };
net/ipv4/inet_timewait_sock.c +3 -6
@@ -282,7 +282,7 @@ void __inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo, bool rearm)EXPORT_SYMBOL_GPL (__inet_twsk_schedule);/* Remove all non full sockets (TIME_WAIT and NEW_SYN_RECV) for dead netns */ -void inet_twsk_purge (struct inet_hashinfo *hashinfo,int family) +void inet_twsk_purge (struct inet_hashinfo *hashinfo) {struct inet_ehash_bucket *head = &hashinfo->ehash[0 ];unsigned int ehash_mask = hashinfo->ehash_mask;
@@ -291,7 +291,6 @@ void inet_twsk_purge(struct inet_hashinfo *hashinfo, int family)struct sock *sk;for (slot =0 ; slot <= ehash_mask; slot++, head++) { -if (hlist_nulls_empty (&head->chain))continue ;
@@ -306,15 +305,13 @@ void inet_twsk_purge(struct inet_hashinfo *hashinfo, int family) TCPF_NEW_SYN_RECV))continue ; -if (sk->sk_family != family || -refcount_read (&sock_net (sk)->ns.count)) +if (refcount_read (&sock_net (sk)->ns.count))continue ;if (unlikely (!refcount_inc_not_zero (&sk->sk_refcnt)))continue ; -if (unlikely (sk->sk_family != family || -refcount_read (&sock_net (sk)->ns.count))) { +if (refcount_read (&sock_net (sk)->ns.count)) {sock_gen_put (sk); goto restart; }
net/ipv4/tcp_ipv4.c +1 -1
@@ -3242,7 +3242,7 @@ static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) {struct net *net; -tcp_twsk_purge (net_exit_list,AF_INET ); +tcp_twsk_purge (net_exit_list);list_for_each_entry (net, net_exit_list, exit_list) {inet_pernet_hashinfo_free (net->ipv4.tcp_death_row.hashinfo);
net/ipv4/tcp_minisocks.c +3 -3
@@ -347,7 +347,7 @@ void tcp_twsk_destructor(struct sock *sk) }EXPORT_SYMBOL_GPL (tcp_twsk_destructor); -void tcp_twsk_purge (struct list_head *net_exit_list,int family) +void tcp_twsk_purge (struct list_head *net_exit_list) {bool purged_once = false;struct net *net;
@@ -355,9 +355,9 @@ void tcp_twsk_purge(struct list_head *net_exit_list, int family)list_for_each_entry (net, net_exit_list, exit_list) {if (net->ipv4.tcp_death_row.hashinfo->pernet) {/* Even if tw_refcount == 1, we must clean up kernel reqsk */ -inet_twsk_purge (net->ipv4.tcp_death_row.hashinfo, family); +inet_twsk_purge (net->ipv4.tcp_death_row.hashinfo); }else if (!purged_once) { -inet_twsk_purge (&tcp_hashinfo, family); +inet_twsk_purge (&tcp_hashinfo); purged_once = true; } }
net/ipv6/tcp_ipv6.c +0 -6
@@ -2217,15 +2217,9 @@ static void __net_exit tcpv6_net_exit(struct net *net)inet_ctl_sock_destroy (net->ipv6.tcp_sk); } -static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list) -{ -tcp_twsk_purge (net_exit_list,AF_INET6 ); -} -static struct pernet_operations tcpv6_net_ops = { .init = tcpv6_net_init, .exit = tcpv6_net_exit, - .exit_batch = tcpv6_net_exit_batch, };int __init tcpv6_init (void )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 232/321 tcp: prevent concurrent execution of tcp_sk_exit_batch
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 565d121b69980637f040eb4d84289869cdaabedf ]
Its possible that two threads call tcp_sk_exit_batch() concurrently, once from the cleanup_net workqueue, once from a task that failed to clone a new netns. In the latter case, error unwinding calls the exit handlers in reverse order for the 'failed' netns.
tcp_sk_exit_batch() calls tcp_twsk_purge().
Problem is that since commit b099ce2602d8 ("net: Batch inet_twsk_purge"), this function picks up twsk in any dying netns, not just the one passed in via exit_batch list.
This means that the error unwind of setup_net() can "steal" and destroy timewait sockets belonging to the exiting netns.
This allows the netns exit worker to proceed to call
WARN_ON_ONCE(!refcount_dec_and_test(&net->ipv4.tcp_death_row.tw_refcount));
without the expected 1 -> 0 transition, which then splats.
At same time, error unwind path that is also running inet_twsk_purge() will splat as well:
WARNING: .. at lib/refcount.c:31 refcount_warn_saturate+0x1ed/0x210
...
refcount_dec include/linux/refcount.h:351 [inline] inet_twsk_kill+0x758/0x9c0 net/ipv4/inet_timewait_sock.c:70 inet_twsk_deschedule_put net/ipv4/inet_timewait_sock.c:221 inet_twsk_purge+0x725/0x890 net/ipv4/inet_timewait_sock.c:304 tcp_sk_exit_batch+0x1c/0x170 net/ipv4/tcp_ipv4.c:3522 ops_exit_list+0x128/0x180 net/core/net_namespace.c:178 setup_net+0x714/0xb40 net/core/net_namespace.c:375 copy_net_ns+0x2f0/0x670 net/core/net_namespace.c:508 create_new_namespaces+0x3ea/0xb10 kernel/nsproxy.c:110
... because refcount_dec() of tw_refcount unexpectedly dropped to 0.
This doesn't seem like an actual bug (no tw sockets got lost and I don't see a use-after-free) but as erroneous trigger of debug check.
Add a mutex to force strict ordering: the task that calls tcp_twsk_purge() blocks other task from doing final _dec_and_test before mutex-owner has removed all tw sockets of dying netns.
--- net/ipv4/tcp_ipv4.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
net/ipv4/tcp_ipv4.c +14 -0
@@ -93,6 +93,8 @@ EXPORT_SYMBOL(tcp_hashinfo); static DEFINE_PER_CPU(struct sock *, ipv4_tcp_sk); +static DEFINE_MUTEX (tcp_exit_batch_mutex); +static u32 tcp_v4_init_seq (const struct sk_buff *skb) { return secure_tcp_seq(ip_hdr(skb)->daddr,
@@ -3242,6 +3244,16 @@ static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) {struct net *net; +/* make sure concurrent calls to tcp_sk_exit_batch from net_cleanup_work +* and failed setup_net error unwinding path are serialized. +* +* tcp_twsk_purge() handles twsk in any dead netns, not just those in +* net_exit_list, the thread that dismantles a particular twsk must +* do so without other thread progressing to refcount_dec_and_test() of +* tcp_death_row.tw_refcount. +*/ +mutex_lock (&tcp_exit_batch_mutex); +tcp_twsk_purge (net_exit_list);list_for_each_entry (net, net_exit_list, exit_list) {
@@ -3249,6 +3261,8 @@ static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)WARN_ON_ONCE (!refcount_dec_and_test (&net->ipv4.tcp_death_row.tw_refcount));tcp_fastopen_ctx_destroy (net); } + +mutex_unlock (&tcp_exit_batch_mutex); }static struct pernet_operations __net_initdata tcp_sk_ops = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 233/321 net: mctp: test: Use correct skb for route input check
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeremy Kerr <[email protected]>
[ Upstream commit ce335db0621648472f9bb4b7191eb2e13a5793cf ]
In the MCTP route input test, we're routing one skb, then (when delivery is expected) checking the resulting routed skb.
However, we're currently checking the original skb length, rather than the routed skb. Check the routed skb instead; the original will have been freed at this point.
--- net/mctp/test/route-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mctp/test/route-test.c +1 -1
@@ -354,7 +354,7 @@ static void mctp_test_route_input_sk(struct kunit *test) skb2 =skb_recv_datagram (sock->sk,MSG_DONTWAIT , &rc);KUNIT_EXPECT_NOT_ERR_OR_NULL (test, skb2); -KUNIT_EXPECT_EQ (test, skb->len,1 ); +KUNIT_EXPECT_EQ (test, skb2->len,1 );skb_free_datagram (sock->sk, skb2);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 234/321 kcm: Serialise kcm_sendmsg() for the same socket.
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 807067bf014d4a3ae2cc55bd3de16f22a01eb580 ]
syzkaller reported UAF in kcm_release(). [0]
The scenario is
1. Thread A builds a skb with MSG_MORE and sets kcm->seq_skb.
2. Thread A resumes building skb from kcm->seq_skb but is blocked by sk_stream_wait_memory()
3. Thread B calls sendmsg() concurrently, finishes building kcm->seq_skb and puts the skb to the write queue
4. Thread A faces an error and finally frees skb that is already in the write queue
5. kcm_release() does double-free the skb in the write queue
When a thread is building a MSG_MORE skb, another thread must not touch it.
Let's add a per-sk mutex and serialise kcm_sendmsg().
[0]:
BUG: KASAN: slab-use-after-free in __skb_unlink include/linux/skbuff.h:2366 [inline] BUG: KASAN: slab-use-after-free in __skb_dequeue include/linux/skbuff.h:2385 [inline] BUG: KASAN: slab-use-after-free in __skb_queue_purge_reason include/linux/skbuff.h:3175 [inline] BUG: KASAN: slab-use-after-free in __skb_queue_purge include/linux/skbuff.h:3181 [inline] BUG: KASAN: slab-use-after-free in kcm_release+0x170/0x4c8 net/kcm/kcmsock.c:1691 Read of size 8 at addr ffff0000ced0fc80 by task syz-executor329/6167 CPU: 1 PID: 6167 Comm: syz-executor329 Tainted: G B 6.8.0-rc5-syzkaller-g9abbc24128bc #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/25/2024 Call trace: dump_backtrace+0x1b8/0x1e4 arch/arm64/kernel/stacktrace.c:291 show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:298 __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xd0/0x124 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:377 [inline] print_report+0x178/0x518 mm/kasan/report.c:488 kasan_report+0xd8/0x138 mm/kasan/report.c:601 __asan_report_load8_noabort+0x20/0x2c mm/kasan/report_generic.c:381 __skb_unlink include/linux/skbuff.h:2366 [inline] __skb_dequeue include/linux/skbuff.h:2385 [inline] __skb_queue_purge_reason include/linux/skbuff.h:3175 [inline] __skb_queue_purge include/linux/skbuff.h:3181 [inline] kcm_release+0x170/0x4c8 net/kcm/kcmsock.c:1691 __sock_release net/socket.c:659 [inline] sock_close+0xa4/0x1e8 net/socket.c:1421 __fput+0x30c/0x738 fs/file_table.c:376 ____fput+0x20/0x30 fs/file_table.c:404 task_work_run+0x230/0x2e0 kernel/task_work.c:180 exit_task_work include/linux/task_work.h:38 [inline] do_exit+0x618/0x1f64 kernel/exit.c:871 do_group_exit+0x194/0x22c kernel/exit.c:1020 get_signal+0x1500/0x15ec kernel/signal.c:2893 do_signal+0x23c/0x3b44 arch/arm64/kernel/signal.c:1249 do_notify_resume+0x74/0x1f4 arch/arm64/kernel/entry-common.c:148 exit_to_user_mode_prepare arch/arm64/kernel/entry-common.c:169 [inline] exit_to_user_mode arch/arm64/kernel/entry-common.c:178 [inline] el0_svc+0xac/0x168 arch/arm64/kernel/entry-common.c:713 el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 Allocated by task 6166: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x40/0x78 mm/kasan/common.c:68 kasan_save_alloc_info+0x70/0x84 mm/kasan/generic.c:626 unpoison_slab_object mm/kasan/common.c:314 [inline] __kasan_slab_alloc+0x74/0x8c mm/kasan/common.c:340 kasan_slab_alloc include/linux/kasan.h:201 [inline] slab_post_alloc_hook mm/slub.c:3813 [inline] slab_alloc_node mm/slub.c:3860 [inline] kmem_cache_alloc_node+0x204/0x4c0 mm/slub.c:3903 __alloc_skb+0x19c/0x3d8 net/core/skbuff.c:641 alloc_skb include/linux/skbuff.h:1296 [inline] kcm_sendmsg+0x1d3c/0x2124 net/kcm/kcmsock.c:783 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg net/socket.c:745 [inline] sock_sendmsg+0x220/0x2c0 net/socket.c:768 splice_to_socket+0x7cc/0xd58 fs/splice.c:889 do_splice_from fs/splice.c:941 [inline] direct_splice_actor+0xec/0x1d8 fs/splice.c:1164 splice_direct_to_actor+0x438/0xa0c fs/splice.c:1108 do_splice_direct_actor fs/splice.c:1207 [inline] do_splice_direct+0x1e4/0x304 fs/splice.c:1233 do_sendfile+0x460/0xb3c fs/read_write.c:1295 __do_sys_sendfile64 fs/read_write.c:1362 [inline] __se_sys_sendfile64 fs/read_write.c:1348 [inline] __arm64_sys_sendfile64+0x160/0x3b4 fs/read_write.c:1348 __invoke_syscall arch/arm64/kernel/syscall.c:37 [inline] invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:51 el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:136 do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:155 el0_svc+0x54/0x168 arch/arm64/kernel/entry-common.c:712 el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 Freed by task 6167: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x40/0x78 mm/kasan/common.c:68 kasan_save_free_info+0x5c/0x74 mm/kasan/generic.c:640 poison_slab_object+0x124/0x18c mm/kasan/common.c:241 __kasan_slab_free+0x3c/0x78 mm/kasan/common.c:257 kasan_slab_free include/linux/kasan.h:184 [inline] slab_free_hook mm/slub.c:2121 [inline] slab_free mm/slub.c:4299 [inline] kmem_cache_free+0x15c/0x3d4 mm/slub.c:4363 kfree_skbmem+0x10c/0x19c __kfree_skb net/core/skbuff.c:1109 [inline] kfree_skb_reason+0x240/0x6f4 net/core/skbuff.c:1144 kfree_skb include/linux/skbuff.h:1244 [inline] kcm_release+0x104/0x4c8 net/kcm/kcmsock.c:1685 __sock_release net/socket.c:659 [inline] sock_close+0xa4/0x1e8 net/socket.c:1421 __fput+0x30c/0x738 fs/file_table.c:376 ____fput+0x20/0x30 fs/file_table.c:404 task_work_run+0x230/0x2e0 kernel/task_work.c:180 exit_task_work include/linux/task_work.h:38 [inline] do_exit+0x618/0x1f64 kernel/exit.c:871 do_group_exit+0x194/0x22c kernel/exit.c:1020 get_signal+0x1500/0x15ec kernel/signal.c:2893 do_signal+0x23c/0x3b44 arch/arm64/kernel/signal.c:1249 do_notify_resume+0x74/0x1f4 arch/arm64/kernel/entry-common.c:148 exit_to_user_mode_prepare arch/arm64/kernel/entry-common.c:169 [inline] exit_to_user_mode arch/arm64/kernel/entry-common.c:178 [inline] el0_svc+0xac/0x168 arch/arm64/kernel/entry-common.c:713 el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 The buggy address belongs to the object at ffff0000ced0fc80 which belongs to the cache skbuff_head_cache of size 240
The buggy address is located 0 bytes inside of
freed 240-byte region [ffff0000ced0fc80, ffff0000ced0fd70)
The buggy address belongs to the physical page:
page:00000000d35f4ae4 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10ed0f
flags: 0x5ffc00000000800(slab|node=0|zone=2|lastcpupid=0x7ff)
page_type: 0xffffffff()
raw: 05ffc00000000800 ffff0000c1cbf640 fffffdffc3423100 dead000000000004
raw: 0000000000000000 00000000000c000c 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff0000ced0fb80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff0000ced0fc00: fb fb fb fb fb fb fc fc fc fc fc fc fc fc fc fc
>ffff0000ced0fc80: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff0000ced0fd00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fc fc
ffff0000ced0fd80: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb--- include/net/kcm.h | 1 + net/kcm/kcmsock.c | 4 ++++ 2 files changed, 5 insertions(+)
include/net/kcm.h +1 -0
@@ -70,6 +70,7 @@ struct kcm_sock {struct work_struct tx_work;struct list_head wait_psock_list;struct sk_buff *seq_skb; +struct mutex tx_mutex; u32 tx_stopped : 1;/* Don't use bit fields here, these are set under different locks */
net/kcm/kcmsock.c +4 -0
@@ -912,6 +912,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) !(msg->msg_flags & MSG_MORE) : !!(msg->msg_flags & MSG_EOR);int err = -EPIPE ; +mutex_lock (&kcm->tx_mutex);lock_sock (sk);/* Per tcp_sendmsg this should be in poll */
@@ -1060,6 +1061,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)KCM_STATS_ADD (kcm->stats.tx_bytes, copied);release_sock (sk); +mutex_unlock (&kcm->tx_mutex);return copied; out_error:
@@ -1085,6 +1087,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) sk->sk_write_space (sk);release_sock (sk); +mutex_unlock (&kcm->tx_mutex);return err; }
@@ -1325,6 +1328,7 @@ static void init_kcm_sock(struct kcm_sock *kcm, struct kcm_mux *mux)spin_unlock_bh (&mux->lock);INIT_WORK (&kcm->tx_work, kcm_tx_work); +mutex_init (&kcm->tx_mutex);spin_lock_bh (&mux->rx_lock);kcm_rcv_ready (kcm);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 235/321 netfilter: nft_counter: Disable BH in nft_counter_offload_stats().
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit 1eacdd71b3436b54d5fc8218c4bb0187d92a6892 ]
The sequence counter nft_counter_seq is a per-CPU counter. There is no lock associated with it. nft_counter_do_eval() is using the same counter and disables BH which suggest that it can be invoked from a softirq. This in turn means that nft_counter_offload_stats(), which disables only preemption, can be interrupted by nft_counter_do_eval() leading to two writer for one seqcount_t.
This can lead to loosing stats or reading statistics while they are updated.
Disable BH during stats update in nft_counter_offload_stats() to ensure one writer at a time.
--- net/netfilter/nft_counter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/nft_counter.c +2 -2
@@ -264,7 +264,7 @@ static void nft_counter_offload_stats(struct nft_expr *expr,struct nft_counter *this_cpu;seqcount_t *myseq; -preempt_disable (); +local_bh_disable (); this_cpu =this_cpu_ptr (priv->counter); myseq =this_cpu_ptr (&nft_counter_seq);
@@ -272,7 +272,7 @@ static void nft_counter_offload_stats(struct nft_expr *expr, this_cpu->packets += stats->pkts; this_cpu->bytes += stats->bytes;write_seqcount_end (myseq); -preempt_enable (); +local_bh_enable (); }void nft_counter_init_seqcount (void )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 236/321 netfilter: nft_counter: Synchronize nft_counter_reset() against reader.
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit a0b39e2dc7017ac667b70bdeee5293e410fab2fb ]
nft_counter_reset() resets the counter by subtracting the previously retrieved value from the counter. This is a write operation on the counter and as such it requires to be performed with a write sequence of nft_counter_seq to serialize against its possible reader.
Update the packets/ bytes within write-sequence of nft_counter_seq.
--- net/netfilter/nft_counter.c | 5 +++++ 1 file changed, 5 insertions(+)
net/netfilter/nft_counter.c +5 -0
@@ -107,11 +107,16 @@ static void nft_counter_reset(struct nft_counter_percpu_priv *priv, struct nft_counter *total) {struct nft_counter *this_cpu; +seqcount_t *myseq;local_bh_disable (); this_cpu =this_cpu_ptr (priv->counter); + myseq =this_cpu_ptr (&nft_counter_seq); + +write_seqcount_begin (myseq); this_cpu->packets -= total->packets; this_cpu->bytes -= total->bytes; +write_seqcount_end (myseq);local_bh_enable (); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 237/321 ip6_tunnel: Fix broken GRO
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Bogendoerfer <[email protected]>
[ Upstream commit 4b3e33fcc38f7750604b065c55a43e94c5bc3145 ]
GRO code checks for matching layer 2 headers to see, if packet belongs to the same flow and because ip6 tunnel set dev->hard_header_len this check fails in cases, where it shouldn't. To fix this don't set hard_header_len, but use needed_headroom like ipv4/ip_tunnel.c does.
--- net/ipv6/ip6_tunnel.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
net/ipv6/ip6_tunnel.c +7 -5
@@ -1510,7 +1510,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) tdev =__dev_get_by_index (t->net, p->link);if (tdev) { - dev->hard_header_len = tdev->hard_header_len + t_hlen; + dev->needed_headroom = tdev->hard_header_len + + tdev->needed_headroom + t_hlen; mtu = min_t(unsigned int, tdev->mtu, IP6_MAX_MTU); mtu = mtu - t_hlen;
@@ -1734,7 +1735,9 @@ ip6_tnl_siocdevprivate(struct net_device *dev, struct ifreq *ifr,int ip6_tnl_change_mtu (struct net_device *dev,int new_mtu) {struct ip6_tnl *tnl =netdev_priv (dev); +int t_hlen; + t_hlen = tnl->hlen +sizeof (struct ipv6hdr );if (tnl->parms.proto ==IPPROTO_IPV6 ) {if (new_mtu <IPV6_MIN_MTU )return -EINVAL ;
@@ -1743,10 +1746,10 @@ int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)return -EINVAL ; }if (tnl->parms.proto ==IPPROTO_IPV6 || tnl->parms.proto ==0 ) { -if (new_mtu >IP6_MAX_MTU - dev->hard_header_len) +if (new_mtu >IP6_MAX_MTU - dev->hard_header_len - t_hlen)return -EINVAL ; }else { -if (new_mtu >IP_MAX_MTU - dev->hard_header_len) +if (new_mtu >IP_MAX_MTU - dev->hard_header_len - t_hlen)return -EINVAL ; } dev->mtu = new_mtu;
@@ -1892,12 +1895,11 @@ ip6_tnl_dev_init_gen(struct net_device *dev) t_hlen = t->hlen +sizeof (struct ipv6hdr ); dev->type =ARPHRD_TUNNEL6 ; - dev->hard_header_len =LL_MAX_HEADER + t_hlen; dev->mtu =ETH_DATA_LEN - t_hlen;if (!(t->parms.flags &IP6_TNL_F_IGN_ENCAP_LIMIT )) dev->mtu -=8 ; dev->min_mtu =ETH_MIN_MTU ; - dev->max_mtu =IP6_MAX_MTU - dev->hard_header_len; + dev->max_mtu =IP6_MAX_MTU - dev->hard_header_len - t_hlen;netdev_hold (dev, &t->dev_tracker,GFP_KERNEL );return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 238/321 bonding: fix bond_ipsec_offload_ok return type
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit fc59b9a5f7201b9f7272944596113a82cc7773d5 ]
Fix the return type which should be bool.
--- drivers/net/bonding/bond_main.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-)
drivers/net/bonding/bond_main.c +6 -12
@@ -595,34 +595,28 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)struct net_device *real_dev;struct slave *curr_active;struct bonding *bond; -int err; +bool ok = false; bond =netdev_priv (bond_dev);rcu_read_lock (); curr_active =rcu_dereference (bond->curr_active_slave); real_dev = curr_active->dev; -if (BOND_MODE (bond) !=BOND_MODE_ACTIVEBACKUP ) { - err = false; +if (BOND_MODE (bond) !=BOND_MODE_ACTIVEBACKUP ) goto out; - } -if (!xs->xso.real_dev) { - err = false; +if (!xs->xso.real_dev) goto out; - }if (!real_dev->xfrmdev_ops || !real_dev->xfrmdev_ops->xdo_dev_offload_ok || -netif_is_bond_master (real_dev)) { - err = false; +netif_is_bond_master (real_dev)) goto out; - } - err = real_dev->xfrmdev_ops->xdo_dev_offload_ok (skb, xs); + ok = real_dev->xfrmdev_ops->xdo_dev_offload_ok (skb, xs); out:rcu_read_unlock (); -return err; +return ok; }static const struct xfrmdev_ops bond_xfrmdev_ops = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 239/321 bonding: fix null pointer deref in bond_ipsec_offload_ok
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit 95c90e4ad89d493a7a14fa200082e466e2548f9d ]
We must check if there is an active slave before dereferencing the pointer.
--- drivers/net/bonding/bond_main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/bonding/bond_main.c +2 -0
@@ -600,6 +600,8 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs) bond =netdev_priv (bond_dev);rcu_read_lock (); curr_active =rcu_dereference (bond->curr_active_slave); +if (!curr_active) + goto out; real_dev = curr_active->dev;if (BOND_MODE (bond) !=BOND_MODE_ACTIVEBACKUP )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 240/321 bonding: fix xfrm real_dev null pointer dereference
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit f8cde9805981c50d0c029063dc7d82821806fc44 ]
We shouldn't set real_dev to NULL because packets can be in transit and xfrm might call xdo_dev_offload_ok() in parallel. All callbacks assume real_dev is set.
Example trace:
kernel: BUG: unable to handle page fault for address: 0000000000001030
kernel: bond0: (slave eni0np1): making interface the new active one
kernel: #PF: supervisor write access in kernel mode
kernel: #PF: error_code(0x0002) - not-present page
kernel: PGD 0 P4D 0
kernel: Oops: 0002 [#1] PREEMPT SMP
kernel: CPU: 4 PID: 2237 Comm: ping Not tainted 6.7.7+ #12
kernel: Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014
kernel: RIP: 0010:nsim_ipsec_offload_ok+0xc/0x20 [netdevsim]
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel: Code: e0 0f 0b 48 83 7f 38 00 74 de 0f 0b 48 8b 47 08 48 8b 37 48 8b 78 40 e9 b2 e5 9a d7 66 90 0f 1f 44 00 00 48 8b 86 80 02 00 00 <83> 80 30 10 00 00 01 b8 01 00 00 00 c3 0f 1f 80 00 00 00 00 0f 1f
kernel: bond0: (slave eni0np1): making interface the new active one
kernel: RSP: 0018:ffffabde81553b98 EFLAGS: 00010246
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel:
kernel: RAX: 0000000000000000 RBX: ffff9eb404e74900 RCX: ffff9eb403d97c60
kernel: RDX: ffffffffc090de10 RSI: ffff9eb404e74900 RDI: ffff9eb3c5de9e00
kernel: RBP: ffff9eb3c0a42000 R08: 0000000000000010 R09: 0000000000000014
kernel: R10: 7974203030303030 R11: 3030303030303030 R12: 0000000000000000
kernel: R13: ffff9eb3c5de9e00 R14: ffffabde81553cc8 R15: ffff9eb404c53000
kernel: FS: 00007f2a77a3ad00(0000) GS:ffff9eb43bd00000(0000) knlGS:0000000000000000
kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
kernel: CR2: 0000000000001030 CR3: 00000001122ab000 CR4: 0000000000350ef0
kernel: bond0: (slave eni0np1): making interface the new active one
kernel: Call Trace:
kernel: <TASK>
kernel: ? __die+0x1f/0x60
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel: ? page_fault_oops+0x142/0x4c0 kernel: ? do_user_addr_fault+0x65/0x670 kernel: ? kvm_read_and_reset_apf_flags+0x3b/0x50 kernel: bond0: (slave eni0np1): making interface the new active one kernel: ? exc_page_fault+0x7b/0x180 kernel: ? asm_exc_page_fault+0x22/0x30 kernel: ? nsim_bpf_uninit+0x50/0x50 [netdevsim]
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel: ? nsim_ipsec_offload_ok+0xc/0x20 [netdevsim]
kernel: bond0: (slave eni0np1): making interface the new active one
kernel: bond_ipsec_offload_ok+0x7b/0x90 [bonding]
kernel: xfrm_output+0x61/0x3b0
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel: ip_push_pending_frames+0x56/0x80
--- drivers/net/bonding/bond_main.c | 1 - 1 file changed, 1 deletion(-)
drivers/net/bonding/bond_main.c +0 -1
@@ -578,7 +578,6 @@ static void bond_ipsec_del_sa_all(struct bonding *bond) }else { slave->dev->xfrmdev_ops->xdo_dev_state_delete (ipsec->xs); } - ipsec->xs->xso.real_dev =NULL ; }spin_unlock_bh (&bond->ipsec_lock);rcu_read_unlock ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 241/321 bonding: fix xfrm state handling when clearing active slave
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit c4c5c5d2ef40a9f67a9241dc5422eac9ffe19547 ]
If the active slave is cleared manually the xfrm state is not flushed. This leads to xfrm add/del imbalance and adding the same state multiple times. For example when the device cannot handle anymore states we get:
[ 1169.884811] bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
because it's filled with the same state after multiple active slave clearings. This change also has a few nice side effects: user-space gets a notification for the change, the old device gets its mac address and promisc/mcast adjusted properly.
--- drivers/net/bonding/bond_options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/bonding/bond_options.c +1 -1
@@ -932,7 +932,7 @@ static int bond_option_active_slave_set(struct bonding *bond,/* check to see if we are clearing active */ if (!slave_dev) {netdev_dbg (bond->dev,"Clearing current active slave\n" ); -RCU_INIT_POINTER (bond->curr_active_slave,NULL ); +bond_change_active_slave (bond,NULL );bond_select_active_slave (bond); }else {struct slave *old_active =rtnl_dereference (bond->curr_active_slave);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 242/321 ice: Prepare legacy-rx for upcoming XDP multi-buffer support
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit c61bcebde72de7f5dc194d28f29894f0f7661ff7 ]
Rx path is going to be modified in a way that fragmented frame will be gathered within xdp_buff in the first place. This approach implies that underlying buffer has to provide tailroom for skb_shared_info. This is currently the case when ring uses build_skb but not when legacy-rx knob is turned on. This case configures 2k Rx buffers and has no way to provide either headroom or tailroom - FWIW it currently has XDP_PACKET_HEADROOM which is broken and in here it is removed. 2k Rx buffers were used so driver in this setting was able to support 9k MTU as it can chain up to 5 Rx buffers. With offset configuring HW writing 2k of a data was passing the half of the page which broke the assumption of our internal page recycling tricks.
Now if above got fixed and legacy-rx path would be left as is, when referring to skb_shared_info via xdp_get_shared_info_from_buff(), packet's content would be corrupted again. Hence size of Rx buffer needs to be lowered and therefore supported MTU. This operation will allow us to keep the unified data path and with 8k MTU users (if any of legacy-rx) would still be good to go. However, tendency is to drop the support for this code path at some point.
Add ICE_RXBUF_1664 as vsi::rx_buf_len and ICE_MAX_FRAME_LEGACY_RX (8320) as vsi::max_frame for legacy-rx. For bigger page sizes configure 3k Rx buffers, not 2k.
Since headroom support is removed, disable data_meta support on legacy-rx. When preparing XDP buff, rely on ice_rx_ring::rx_offset setting when deciding whether to support data_meta or not.
Stable-dep-of: 50b2143356e8 ("ice: fix page reuse when PAGE_SIZE is over 8k")
--- drivers/net/ethernet/intel/ice/ice_base.c | 3 --- drivers/net/ethernet/intel/ice/ice_lib.c | 8 ++------ drivers/net/ethernet/intel/ice/ice_main.c | 10 ++++++++-- drivers/net/ethernet/intel/ice/ice_txrx.c | 17 +++++------------ drivers/net/ethernet/intel/ice/ice_txrx.h | 2 ++ 5 files changed, 17 insertions(+), 23 deletions(-)
drivers/net/ethernet/intel/ice/ice_base.c +0 -3
@@ -355,9 +355,6 @@ static unsigned int ice_rx_offset(struct ice_rx_ring *rx_ring) {if (ice_ring_uses_build_skb (rx_ring))return ICE_SKB_PAD ; -else if (ice_is_xdp_ena_vsi (rx_ring->vsi)) -return XDP_PACKET_HEADROOM ; -return 0 ; }
drivers/net/ethernet/intel/ice/ice_lib.c +2 -6
@@ -1818,8 +1818,8 @@ void ice_update_eth_stats(struct ice_vsi *vsi)void ice_vsi_cfg_frame_size (struct ice_vsi *vsi) {if (!vsi->netdev ||test_bit (ICE_FLAG_LEGACY_RX , vsi->back->flags)) { - vsi->max_frame =ICE_AQ_SET_MAC_FRAME_SIZE_MAX ; - vsi->rx_buf_len =ICE_RXBUF_2048 ; + vsi->max_frame =ICE_MAX_FRAME_LEGACY_RX ; + vsi->rx_buf_len =ICE_RXBUF_1664 ;#if (PAGE_SIZE <8192 ) } else if (!ICE_2K_TOO_SMALL_WITH_PADDING && (vsi->netdev->mtu <=ETH_DATA_LEN )) {
@@ -1828,11 +1828,7 @@ void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)#endif }else { vsi->max_frame =ICE_AQ_SET_MAC_FRAME_SIZE_MAX ; -#if (PAGE_SIZE <8192 ) vsi->rx_buf_len =ICE_RXBUF_3072 ; -#else - vsi->rx_buf_len =ICE_RXBUF_2048 ; -#endif } }
drivers/net/ethernet/intel/ice/ice_main.c +8 -2
@@ -7328,8 +7328,8 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)*/ static int ice_max_xdp_frame_size (struct ice_vsi *vsi) { -if (PAGE_SIZE >=8192 ||test_bit (ICE_FLAG_LEGACY_RX , vsi->back->flags)) -return ICE_RXBUF_2048 -XDP_PACKET_HEADROOM ; +if (test_bit (ICE_FLAG_LEGACY_RX , vsi->back->flags)) +return ICE_RXBUF_1664 ;else return ICE_RXBUF_3072 ; }
@@ -7362,6 +7362,12 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu) frame_size - ICE_ETH_PKT_HDR_PAD);return -EINVAL ; } + }else if (test_bit (ICE_FLAG_LEGACY_RX , pf->flags)) { +if (new_mtu +ICE_ETH_PKT_HDR_PAD >ICE_MAX_FRAME_LEGACY_RX ) { +netdev_err (netdev,"Too big MTU for legacy-rx; Max is %d\n" , +ICE_MAX_FRAME_LEGACY_RX -ICE_ETH_PKT_HDR_PAD ); +return -EINVAL ; + } }/* if a reset is in progress, wait for some time for it to complete */
drivers/net/ethernet/intel/ice/ice_txrx.c +5 -12
@@ -984,17 +984,15 @@ static struct sk_buff * ice_construct_skb(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf, struct xdp_buff *xdp) { - unsigned int metasize = xdp->data - xdp->data_meta; unsigned int size = xdp->data_end - xdp->data;unsigned int headlen;struct sk_buff *skb;/* prefetch first cache line of first page */ -net_prefetch (xdp->data_meta); +net_prefetch (xdp->data);/* allocate a skb to store the frags */ - skb =__napi_alloc_skb (&rx_ring->q_vector->napi, -ICE_RX_HDR_SIZE + metasize, + skb =__napi_alloc_skb (&rx_ring->q_vector->napi,ICE_RX_HDR_SIZE ,GFP_ATOMIC | __GFP_NOWARN);if (unlikely (!skb))return NULL ;
@@ -1006,13 +1004,8 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf, headlen =eth_get_headlen (skb->dev, xdp->data,ICE_RX_HDR_SIZE );/* align pull length to size of long to optimize memcpy performance */ -memcpy (__skb_put (skb, headlen + metasize), xdp->data_meta, -ALIGN (headlen + metasize,sizeof (long ))); - -if (metasize) { -skb_metadata_set (skb, metasize); -__skb_pull (skb, metasize); - } +memcpy (__skb_put (skb, headlen), xdp->data,ALIGN (headlen, +sizeof (long )));/* if we exhaust the linear part then add what is left as a frag */ size -= headlen;
@@ -1187,7 +1180,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) hard_start =page_address (rx_buf->page) + rx_buf->page_offset - offset; -xdp_prepare_buff (&xdp, hard_start, offset, size, true); +xdp_prepare_buff (&xdp, hard_start, offset, size, !!offset);#if (PAGE_SIZE >4096 )/* At larger PAGE_SIZE, frame_sz depend on len size */ xdp.frame_sz =ice_rx_frame_truesize (rx_ring, size);
drivers/net/ethernet/intel/ice/ice_txrx.h +2 -0
@@ -9,10 +9,12 @@#define ICE_DFLT_IRQ_WORK 256#define ICE_RXBUF_3072 3072#define ICE_RXBUF_2048 2048 +#define ICE_RXBUF_1664 1664#define ICE_RXBUF_1536 1536#define ICE_MAX_CHAINED_RX_BUFS 5#define ICE_MAX_BUF_TXD 8#define ICE_MIN_TX_LEN 17 +#define ICE_MAX_FRAME_LEGACY_RX 8320/* The size limit for a transmit buffer in a descriptor is (16K - 1). * In order to align with the read requests we will align the value to
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 243/321 ice: Add xdp_buff to ice_rx_ring struct
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit cb0473e0e9dccaa0ddafb252f2c3ef943b86bb56 ]
In preparation for XDP multi-buffer support, let's store xdp_buff on Rx ring struct. This will allow us to combine fragmented frames across separate NAPI cycles in the same way as currently skb fragments are handled. This means that skb pointer on Rx ring will become redundant and will be removed. For now it is kept and layout of Rx ring struct was not inspected, some member movement will be needed later on so that will be the time to take care of it.
Stable-dep-of: 50b2143356e8 ("ice: fix page reuse when PAGE_SIZE is over 8k")
--- drivers/net/ethernet/intel/ice/ice_base.c | 1 + drivers/net/ethernet/intel/ice/ice_txrx.c | 39 +++++++++++++---------- drivers/net/ethernet/intel/ice/ice_txrx.h | 1 + 3 files changed, 25 insertions(+), 16 deletions(-)
drivers/net/ethernet/intel/ice/ice_base.c +1 -0
@@ -534,6 +534,7 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring) } } +xdp_init_buff (&ring->xdp,ice_rx_pg_size (ring) /2 , &ring->xdp_rxq); err =ice_setup_rx_ctx (ring);if (err) { dev_err(dev, "ice_setup_rx_ctx failed for RxQ %d, err %d\n",
drivers/net/ethernet/intel/ice/ice_txrx.c +23 -16
@@ -523,8 +523,16 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring)return -ENOMEM ; } +/** +* ice_rx_frame_truesize +* @rx_ring: ptr to Rx ring +* @size: size +* +* calculate the truesize with taking into the account PAGE_SIZE of +* underlying arch +*/ static unsigned int -ice_rx_frame_truesize (struct ice_rx_ring *rx_ring,unsigned int __maybe_unused size) +ice_rx_frame_truesize (struct ice_rx_ring *rx_ring,const unsigned int size) {unsigned int truesize;
@@ -1103,21 +1111,20 @@ ice_is_non_eop(struct ice_rx_ring *rx_ring, union ice_32b_rx_flex_desc *rx_desc)*/ int ice_clean_rx_irq (struct ice_rx_ring *rx_ring,int budget) { -unsigned int total_rx_bytes =0 , total_rx_pkts =0 , frame_sz =0 ; +unsigned int total_rx_bytes =0 , total_rx_pkts =0 ;u16 cleaned_count =ICE_DESC_UNUSED (rx_ring);unsigned int offset = rx_ring->rx_offset; +struct xdp_buff *xdp = &rx_ring->xdp;struct ice_tx_ring *xdp_ring =NULL ;unsigned int xdp_res, xdp_xmit =0 ;struct sk_buff *skb = rx_ring->skb;struct bpf_prog *xdp_prog =NULL ; -struct xdp_buff xdp;bool failure;/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */ #if (PAGE_SIZE <8192 ) - frame_sz =ice_rx_frame_truesize (rx_ring,0 ); + xdp->frame_sz =ice_rx_frame_truesize (rx_ring,0 );#endif -xdp_init_buff (&xdp, frame_sz, &rx_ring->xdp_rxq); xdp_prog =READ_ONCE (rx_ring->xdp_prog);if (xdp_prog)
@@ -1171,30 +1178,30 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) rx_buf =ice_get_rx_buf (rx_ring, size, &rx_buf_pgcnt);if (!size) { - xdp.data =NULL ; - xdp.data_end =NULL ; - xdp.data_hard_start =NULL ; - xdp.data_meta =NULL ; + xdp->data =NULL ; + xdp->data_end =NULL ; + xdp->data_hard_start =NULL ; + xdp->data_meta =NULL ; goto construct_skb; } hard_start =page_address (rx_buf->page) + rx_buf->page_offset - offset; -xdp_prepare_buff (&xdp, hard_start, offset, size, !!offset); +xdp_prepare_buff (xdp, hard_start, offset, size, !!offset);#if (PAGE_SIZE >4096 )/* At larger PAGE_SIZE, frame_sz depend on len size */ - xdp.frame_sz =ice_rx_frame_truesize (rx_ring, size); + xdp->frame_sz =ice_rx_frame_truesize (rx_ring, size);#endif if (!xdp_prog) goto construct_skb; - xdp_res =ice_run_xdp (rx_ring, &xdp, xdp_prog, xdp_ring); + xdp_res =ice_run_xdp (rx_ring, xdp, xdp_prog, xdp_ring);if (!xdp_res) goto construct_skb;if (xdp_res & (ICE_XDP_TX |ICE_XDP_REDIR )) { xdp_xmit |= xdp_res; -ice_rx_buf_adjust_pg_offset (rx_buf, xdp.frame_sz); +ice_rx_buf_adjust_pg_offset (rx_buf, xdp->frame_sz); }else { rx_buf->pagecnt_bias++; }
@@ -1207,11 +1214,11 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) construct_skb:if (skb) {ice_add_rx_frag (rx_ring, rx_buf, skb, size); - }else if (likely (xdp.data)) { + }else if (likely (xdp->data)) {if (ice_ring_uses_build_skb (rx_ring)) - skb =ice_build_skb (rx_ring, rx_buf, &xdp); + skb =ice_build_skb (rx_ring, rx_buf, xdp);else - skb =ice_construct_skb (rx_ring, rx_buf, &xdp); + skb =ice_construct_skb (rx_ring, rx_buf, xdp); }/* exit if we failed to retrieve a buffer */ if (!skb) {
drivers/net/ethernet/intel/ice/ice_txrx.h +1 -0
@@ -295,6 +295,7 @@ struct ice_rx_ring {struct bpf_prog *xdp_prog;struct ice_tx_ring *xdp_ring;struct xsk_buff_pool *xsk_pool; +struct xdp_buff xdp;struct sk_buff *skb;dma_addr_t dma;/* physical address of ring */ u64 cached_phctime;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 244/321 ice: Store page count inside ice_rx_buf
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit ac0753391195011ded23696d7882428e5c419a98 ]
This will allow us to avoid carrying additional auxiliary array of page counts when dealing with XDP multi buffer support. Previously combining fragmented frame to skb was not affected in the same way as XDP would be as whole frame is needed to be in place before executing XDP prog. Therefore, when going through HW Rx descriptors one-by-one, calls to ice_put_rx_buf() need to be taken *after* running XDP prog on a potentially multi buffered frame, so some additional storage of page count is needed.
By adding page count to rx buf, it will make it easier to walk through processed entries at the end of rx cleaning routine and decide whether or not buffers should be recycled.
While at it, bump ice_rx_buf::pagecnt_bias from u16 up to u32. It was proven many times that calculations on variables smaller than standard register size are harmful. This was also the case during experiments with embedding page count to ice_rx_buf - when this was added as u16 it had a performance impact.
Stable-dep-of: 50b2143356e8 ("ice: fix page reuse when PAGE_SIZE is over 8k")
--- drivers/net/ethernet/intel/ice/ice_txrx.c | 26 +++++++++-------------- drivers/net/ethernet/intel/ice/ice_txrx.h | 3 ++- 2 files changed, 12 insertions(+), 17 deletions(-)
drivers/net/ethernet/intel/ice/ice_txrx.c +10 -16
@@ -791,7 +791,6 @@ ice_rx_buf_adjust_pg_offset(struct ice_rx_buf *rx_buf, unsigned int size)/** * ice_can_reuse_rx_page - Determine if page can be reused for another Rx * @rx_buf: buffer containing the page -* @rx_buf_pgcnt: rx_buf page refcount pre xdp_do_redirect() call * * If page is reusable, we have a green light for calling ice_reuse_rx_page, * which will assign the current buffer to the buffer that next_to_alloc is
@@ -799,7 +798,7 @@ ice_rx_buf_adjust_pg_offset(struct ice_rx_buf *rx_buf, unsigned int size)* page freed */ static bool -ice_can_reuse_rx_page (struct ice_rx_buf *rx_buf,int rx_buf_pgcnt) +ice_can_reuse_rx_page (struct ice_rx_buf *rx_buf) {unsigned int pagecnt_bias = rx_buf->pagecnt_bias;struct page *page = rx_buf->page;
@@ -810,7 +809,7 @@ ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf, int rx_buf_pgcnt)#if (PAGE_SIZE <8192 )/* if we are only owner of page we can reuse it */ -if (unlikely ((rx_buf_pgcnt - pagecnt_bias) >1 )) +if (unlikely (rx_buf->pgcnt - pagecnt_bias >1 ))return false;#else #define ICE_LAST_OFFSET \
@@ -894,19 +893,17 @@ ice_reuse_rx_page(struct ice_rx_ring *rx_ring, struct ice_rx_buf *old_buf)* ice_get_rx_buf - Fetch Rx buffer and synchronize data for use * @rx_ring: Rx descriptor ring to transact packets on * @size: size of buffer to add to skb -* @rx_buf_pgcnt: rx_buf page refcount * * This function will pull an Rx buffer from the ring and synchronize it * for use by the CPU. */ static struct ice_rx_buf * -ice_get_rx_buf (struct ice_rx_ring *rx_ring,const unsigned int size, -int *rx_buf_pgcnt) +ice_get_rx_buf (struct ice_rx_ring *rx_ring,const unsigned int size) {struct ice_rx_buf *rx_buf; rx_buf = &rx_ring->rx_buf[rx_ring->next_to_clean]; - *rx_buf_pgcnt = + rx_buf->pgcnt =#if (PAGE_SIZE <8192 )page_count (rx_buf->page);#else
@@ -1042,15 +1039,13 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf,* ice_put_rx_buf - Clean up used buffer and either recycle or free * @rx_ring: Rx descriptor ring to transact packets on * @rx_buf: Rx buffer to pull data from -* @rx_buf_pgcnt: Rx buffer page count pre xdp_do_redirect() * * This function will update next_to_clean and then clean up the contents * of the rx_buf. It will either recycle the buffer or unmap it and free * the associated resources. */ static void -ice_put_rx_buf (struct ice_rx_ring *rx_ring,struct ice_rx_buf *rx_buf, -int rx_buf_pgcnt) +ice_put_rx_buf (struct ice_rx_ring *rx_ring,struct ice_rx_buf *rx_buf) {u16 ntc = rx_ring->next_to_clean +1 ;
@@ -1061,7 +1056,7 @@ ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf,if (!rx_buf)return ; -if (ice_can_reuse_rx_page (rx_buf, rx_buf_pgcnt)) { +if (ice_can_reuse_rx_page (rx_buf)) {/* hand second half of page back to the ring */ ice_reuse_rx_page (rx_ring, rx_buf); }else {
@@ -1137,7 +1132,6 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)unsigned char *hard_start;unsigned int size;u16 stat_err_bits; -int rx_buf_pgcnt;u16 vlan_tag =0 ;u16 rx_ptype;
@@ -1166,7 +1160,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)if (rx_desc->wb.rxdid ==FDIR_DESC_RXDID && ctrl_vsi->vf)ice_vc_fdir_irq_handler (ctrl_vsi, rx_desc); -ice_put_rx_buf (rx_ring,NULL ,0 ); +ice_put_rx_buf (rx_ring,NULL ); cleaned_count++;continue ; }
@@ -1175,7 +1169,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)ICE_RX_FLX_DESC_PKT_LEN_M ;/* retrieve a buffer from the ring */ - rx_buf =ice_get_rx_buf (rx_ring, size, &rx_buf_pgcnt); + rx_buf =ice_get_rx_buf (rx_ring, size);if (!size) { xdp->data =NULL ;
@@ -1209,7 +1203,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) total_rx_pkts++; cleaned_count++; -ice_put_rx_buf (rx_ring, rx_buf, rx_buf_pgcnt); +ice_put_rx_buf (rx_ring, rx_buf);continue ; construct_skb:if (skb) {
@@ -1228,7 +1222,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)break ; } -ice_put_rx_buf (rx_ring, rx_buf, rx_buf_pgcnt); +ice_put_rx_buf (rx_ring, rx_buf); cleaned_count++;/* skip if it is NOP desc */
drivers/net/ethernet/intel/ice/ice_txrx.h +2 -1
@@ -172,7 +172,8 @@ struct ice_rx_buf {dma_addr_t dma;struct page *page;unsigned int page_offset; -u16 pagecnt_bias; +unsigned int pgcnt; +unsigned int pagecnt_bias; };struct ice_q_stats {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 245/321 ice: Pull out next_to_clean bump out of ice_put_rx_buf()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit d7956d81f1502d3818500cff4847f3e9ae0c6aa4 ]
Plan is to move ice_put_rx_buf() to the end of ice_clean_rx_irq() so in order to keep the ability of walking through HW Rx descriptors, pull out next_to_clean handling out of ice_put_rx_buf().
Stable-dep-of: 50b2143356e8 ("ice: fix page reuse when PAGE_SIZE is over 8k")
--- drivers/net/ethernet/intel/ice/ice_txrx.c | 29 +++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-)
drivers/net/ethernet/intel/ice/ice_txrx.c +16 -13
@@ -898,11 +898,12 @@ ice_reuse_rx_page(struct ice_rx_ring *rx_ring, struct ice_rx_buf *old_buf)* for use by the CPU. */ static struct ice_rx_buf * -ice_get_rx_buf (struct ice_rx_ring *rx_ring,const unsigned int size) +ice_get_rx_buf (struct ice_rx_ring *rx_ring,const unsigned int size, +const unsigned int ntc) {struct ice_rx_buf *rx_buf; - rx_buf = &rx_ring->rx_buf[rx_ring->next_to_clean]; + rx_buf = &rx_ring->rx_buf[ntc]; rx_buf->pgcnt =#if (PAGE_SIZE <8192 )page_count (rx_buf->page);
@@ -1040,19 +1041,12 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf,* @rx_ring: Rx descriptor ring to transact packets on * @rx_buf: Rx buffer to pull data from * -* This function will update next_to_clean and then clean up the contents -* of the rx_buf. It will either recycle the buffer or unmap it and free -* the associated resources. +* This function will clean up the contents of the rx_buf. It will either +* recycle the buffer or unmap it and free the associated resources. */ static void ice_put_rx_buf (struct ice_rx_ring *rx_ring,struct ice_rx_buf *rx_buf) { -u16 ntc = rx_ring->next_to_clean +1 ; - -/* fetch, update, and store next to clean */ - ntc = (ntc < rx_ring->count) ? ntc :0 ; - rx_ring->next_to_clean = ntc; -if (!rx_buf)return ;
@@ -1114,6 +1108,8 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)unsigned int xdp_res, xdp_xmit =0 ;struct sk_buff *skb = rx_ring->skb;struct bpf_prog *xdp_prog =NULL ; +u32 ntc = rx_ring->next_to_clean; +u32 cnt = rx_ring->count;bool failure;/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */
@@ -1136,7 +1132,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)u16 rx_ptype;/* get the Rx desc from Rx ring based on 'next_to_clean' */ - rx_desc =ICE_RX_DESC (rx_ring, rx_ring->next_to_clean); + rx_desc =ICE_RX_DESC (rx_ring, ntc);/* status_error_len will always be zero for unused descriptors * because it's cleared in cleanup, and overlaps with hdr_addr
@@ -1160,6 +1156,8 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)if (rx_desc->wb.rxdid ==FDIR_DESC_RXDID && ctrl_vsi->vf)ice_vc_fdir_irq_handler (ctrl_vsi, rx_desc); +if (++ntc == cnt) + ntc =0 ;ice_put_rx_buf (rx_ring,NULL ); cleaned_count++;continue ;
@@ -1169,7 +1167,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)ICE_RX_FLX_DESC_PKT_LEN_M ;/* retrieve a buffer from the ring */ - rx_buf =ice_get_rx_buf (rx_ring, size); + rx_buf =ice_get_rx_buf (rx_ring, size, ntc);if (!size) { xdp->data =NULL ;
@@ -1203,6 +1201,8 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) total_rx_pkts++; cleaned_count++; +if (++ntc == cnt) + ntc =0 ;ice_put_rx_buf (rx_ring, rx_buf);continue ; construct_skb:
@@ -1222,6 +1222,8 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)break ; } +if (++ntc == cnt) + ntc =0 ;ice_put_rx_buf (rx_ring, rx_buf); cleaned_count++;
@@ -1262,6 +1264,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) total_rx_pkts++; } + rx_ring->next_to_clean = ntc;/* return up to cleaned_count buffers to hardware */ failure =ice_alloc_rx_bufs (rx_ring, cleaned_count);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 246/321 ice: fix page reuse when PAGE_SIZE is over 8k
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit 50b2143356e888777fc5bca023c39f34f404613a ]
Architectures that have PAGE_SIZE >= 8192 such as arm64 should act the same as x86 currently, meaning reuse of a page should only take place when no one else is busy with it.
Do two things independently of underlying PAGE_SIZE:
- store the page count under ice_rx_buf::pgcnt
- then act upon its value vs ice_rx_buf::pagecnt_bias when making the decision regarding page reuse
--- drivers/net/ethernet/intel/ice/ice_txrx.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
drivers/net/ethernet/intel/ice/ice_txrx.c +3 -9
@@ -807,16 +807,15 @@ ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf)if (!dev_page_is_reusable (page))return false; -#if (PAGE_SIZE <8192 )/* if we are only owner of page we can reuse it */ if (unlikely (rx_buf->pgcnt - pagecnt_bias >1 ))return false; -#else +#if (PAGE_SIZE >=8192 )#define ICE_LAST_OFFSET \ (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_2048)if (rx_buf->page_offset >ICE_LAST_OFFSET )return false; -#endif /* PAGE_SIZE < 8192) */ +#endif /* PAGE_SIZE >= 8192) */ /* If we have drained the page fragment pool we need to update * the pagecnt_bias and page count so that we fully restock the
@@ -904,12 +903,7 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,struct ice_rx_buf *rx_buf; rx_buf = &rx_ring->rx_buf[ntc]; - rx_buf->pgcnt = -#if (PAGE_SIZE <8192 ) -page_count (rx_buf->page); -#else -0 ; -#endif + rx_buf->pgcnt =page_count (rx_buf->page);prefetchw (rx_buf->page);if (!size)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 247/321 ice: fix ICE_LAST_OFFSET formula
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit b966ad832942b5a11e002f9b5ef102b08425b84a ]
For bigger PAGE_SIZE archs, ice driver works on 3k Rx buffers. Therefore, ICE_LAST_OFFSET should take into account ICE_RXBUF_3072, not ICE_RXBUF_2048.
--- drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/ice/ice_txrx.c +1 -1
@@ -812,7 +812,7 @@ ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf)return false;#if (PAGE_SIZE >=8192 )#define ICE_LAST_OFFSET \ - (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_2048) + (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_3072)if (rx_buf->page_offset >ICE_LAST_OFFSET )return false;#endif /* PAGE_SIZE >= 8192) */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 248/321 dpaa2-switch: Fix error checking in dpaa2_switch_seed_bp()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit c50e7475961c36ec4d21d60af055b32f9436b431 ]
The dpaa2_switch_add_bufs() function returns the number of bufs that it was able to add. It returns BUFS_PER_CMD (7) for complete success or a smaller number if there are not enough pages available. However, the error checking is looking at the total number of bufs instead of the number which were added on this iteration. Thus the error checking only works correctly for the first iteration through the loop and subsequent iterations are always counted as a success.
Fix this by checking only the bufs added in the current iteration.
--- drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +4 -3
@@ -2583,13 +2583,14 @@ static int dpaa2_switch_refill_bp(struct ethsw_core *ethsw)static int dpaa2_switch_seed_bp (struct ethsw_core *ethsw) { -int *count, i; +int *count, ret, i;for (i =0 ; i <DPAA2_ETHSW_NUM_BUFS ; i +=BUFS_PER_CMD ) { + ret =dpaa2_switch_add_bufs (ethsw, ethsw->bpid); count = ðsw->buf_count; - *count +=dpaa2_switch_add_bufs (ethsw, ethsw->bpid); + *count += ret; -if (unlikely (*count <BUFS_PER_CMD )) +if (unlikely (ret <BUFS_PER_CMD ))return -ENOMEM ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 249/321 net: dsa: mv88e6xxx: Fix out-of-bound access
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joseph Huang <[email protected]>
[ Upstream commit 528876d867a23b5198022baf2e388052ca67c952 ]
If an ATU violation was caused by a CPU Load operation, the SPID could be larger than DSA_MAX_PORTS (the size of mv88e6xxx_chip.ports[] array).
--- drivers/net/dsa/mv88e6xxx/global1_atu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/dsa/mv88e6xxx/global1_atu.c +2 -1
@@ -453,7 +453,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)trace_mv88e6xxx_atu_full_violation (chip->dev, spid, entry.portvec, entry.mac, fid); - chip->ports[spid].atu_full_violation++; +if (spid <ARRAY_SIZE (chip->ports)) + chip->ports[spid].atu_full_violation++; }mv88e6xxx_reg_unlock (chip);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 250/321 netem: fix return value if duplicate enqueue fails
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Hemminger <[email protected]>
[ Upstream commit c07ff8592d57ed258afee5a5e04991a48dbaf382 ]
There is a bug in netem_enqueue() introduced by
commit 5845f706388a ("net: netem: fix skb length BUG_ON in __skb_to_sgvec") that can lead to a use-after-free.
This commit made netem_enqueue() always return NET_XMIT_SUCCESS when a packet is duplicated, which can cause the parent qdisc's q.qlen to be mistakenly incremented. When this happens qlen_notify() may be skipped on the parent during destruction, leaving a dangling pointer for some classful qdiscs like DRR.
There are two ways for the bug happen:
- If the duplicated packet is dropped by rootq->enqueue() and then the original packet is also dropped.
- If rootq->enqueue() sends the duplicated packet to a different qdisc and the original packet is dropped.
In both cases NET_XMIT_SUCCESS is returned even though no packets are enqueued at the netem qdisc.
The fix is to defer the enqueue of the duplicate packet until after the original packet has been guaranteed to return NET_XMIT_SUCCESS.
--- net/sched/sch_netem.c | 47 ++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 18 deletions(-)
net/sched/sch_netem.c +29 -18
@@ -437,12 +437,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,struct netem_sched_data *q =qdisc_priv (sch);/* We don't fill cb now as skb_unshare() may invalidate it */ struct netem_skb_cb *cb; -struct sk_buff *skb2; +struct sk_buff *skb2 =NULL ;struct sk_buff *segs =NULL ;unsigned int prev_len =qdisc_pkt_len (skb);int count =1 ; -int rc =NET_XMIT_SUCCESS ; -int rc_drop =NET_XMIT_DROP ;/* Do not fool qdisc_drop_all() */ skb->prev =NULL ;
@@ -471,19 +469,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,skb_orphan_partial (skb);/* -* If we need to duplicate packet, then re-insert at top of the -* qdisc tree, since parent queuer expects that only one -* skb will be queued. +* If we need to duplicate packet, then clone it before +* original is modified. */ -if (count >1 && (skb2 =skb_clone (skb,GFP_ATOMIC )) !=NULL ) { -struct Qdisc *rootq =qdisc_root_bh (sch); -u32 dupsave = q->duplicate;/* prevent duplicating a dup... */ - - q->duplicate =0 ; - rootq->enqueue (skb2, rootq, to_free); - q->duplicate = dupsave; - rc_drop =NET_XMIT_SUCCESS ; - } +if (count >1 ) + skb2 =skb_clone (skb,GFP_ATOMIC );/* * Randomized packet corruption.
@@ -495,7 +485,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,if (skb_is_gso (skb)) { skb =netem_segment (skb, sch, to_free);if (!skb) -return rc_drop; + goto finish_segs; + segs = skb->next;skb_mark_not_on_list (skb);qdisc_skb_cb (skb)->pkt_len = skb->len;
@@ -521,7 +512,24 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,/* re-link segs, so that qdisc_drop_all() frees them all */ skb->next = segs;qdisc_drop_all (skb, sch, to_free); -return rc_drop; +if (skb2) +__qdisc_drop (skb2, to_free); +return NET_XMIT_DROP ; + } + +/* +* If doing duplication then re-insert at top of the +* qdisc tree, since parent queuer expects that only one +* skb will be queued. +*/ +if (skb2) { +struct Qdisc *rootq =qdisc_root_bh (sch); +u32 dupsave = q->duplicate;/* prevent duplicating a dup... */ + + q->duplicate =0 ; + rootq->enqueue (skb2, rootq, to_free); + q->duplicate = dupsave; + skb2 =NULL ; }qdisc_qstats_backlog_inc (sch, skb);
@@ -592,9 +600,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, } finish_segs: +if (skb2) +__qdisc_drop (skb2, to_free); +if (segs) {unsigned int len, last_len; -int nb; +int rc, nb; len = skb ? skb->len :0 ; nb = skb ?1 :0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 251/321 ipv6: prevent UAF in ip6_send_skb()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit faa389b2fbaaec7fd27a390b4896139f9da662e3 ]
syzbot reported an UAF in ip6_send_skb() [1]
After ip6_local_out() has returned, we no longer can safely dereference rt, unless we hold rcu_read_lock().
A similar issue has been fixed in commit a688caa34beb ("ipv6: take rcu lock in rawv6_send_hdrinc()")
Another potential issue in ip6_finish_output2() is handled in a separate patch.
[1]
BUG: KASAN: slab-use-after-free in ip6_send_skb+0x18d/0x230 net/ipv6/ip6_output.c:1964 Read of size 8 at addr ffff88806dde4858 by task syz.1.380/6530 CPU: 1 UID: 0 PID: 6530 Comm: syz.1.380 Not tainted 6.11.0-rc3-syzkaller-00306-gdf6cbc62cc9b #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/06/2024 Call Trace: <TASK> __dump_stack lib/dump_stack.c:93 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119 print_address_description mm/kasan/report.c:377 [inline] print_report+0x169/0x550 mm/kasan/report.c:488 kasan_report+0x143/0x180 mm/kasan/report.c:601 ip6_send_skb+0x18d/0x230 net/ipv6/ip6_output.c:1964 rawv6_push_pending_frames+0x75c/0x9e0 net/ipv6/raw.c:588 rawv6_sendmsg+0x19c7/0x23c0 net/ipv6/raw.c:926 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x1a6/0x270 net/socket.c:745 sock_write_iter+0x2dd/0x400 net/socket.c:1160 do_iter_readv_writev+0x60a/0x890 vfs_writev+0x37c/0xbb0 fs/read_write.c:971 do_writev+0x1b1/0x350 fs/read_write.c:1018 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f936bf79e79 Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f936cd7f038 EFLAGS: 00000246 ORIG_RAX: 0000000000000014 RAX: ffffffffffffffda RBX: 00007f936c115f80 RCX: 00007f936bf79e79 RDX: 0000000000000001 RSI: 0000000020000040 RDI: 0000000000000004 RBP: 00007f936bfe7916 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00007f936c115f80 R15: 00007fff2860a7a8 </TASK> Allocated by task 6530: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 unpoison_slab_object mm/kasan/common.c:312 [inline] __kasan_slab_alloc+0x66/0x80 mm/kasan/common.c:338 kasan_slab_alloc include/linux/kasan.h:201 [inline] slab_post_alloc_hook mm/slub.c:3988 [inline] slab_alloc_node mm/slub.c:4037 [inline] kmem_cache_alloc_noprof+0x135/0x2a0 mm/slub.c:4044 dst_alloc+0x12b/0x190 net/core/dst.c:89 ip6_blackhole_route+0x59/0x340 net/ipv6/route.c:2670 make_blackhole net/xfrm/xfrm_policy.c:3120 [inline] xfrm_lookup_route+0xd1/0x1c0 net/xfrm/xfrm_policy.c:3313 ip6_dst_lookup_flow+0x13e/0x180 net/ipv6/ip6_output.c:1257 rawv6_sendmsg+0x1283/0x23c0 net/ipv6/raw.c:898 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x1a6/0x270 net/socket.c:745 ____sys_sendmsg+0x525/0x7d0 net/socket.c:2597 ___sys_sendmsg net/socket.c:2651 [inline] __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2680 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f Freed by task 45: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:579 poison_slab_object+0xe0/0x150 mm/kasan/common.c:240 __kasan_slab_free+0x37/0x60 mm/kasan/common.c:256 kasan_slab_free include/linux/kasan.h:184 [inline] slab_free_hook mm/slub.c:2252 [inline] slab_free mm/slub.c:4473 [inline] kmem_cache_free+0x145/0x350 mm/slub.c:4548 dst_destroy+0x2ac/0x460 net/core/dst.c:124 rcu_do_batch kernel/rcu/tree.c:2569 [inline] rcu_core+0xafd/0x1830 kernel/rcu/tree.c:2843 handle_softirqs+0x2c4/0x970 kernel/softirq.c:554 __do_softirq kernel/softirq.c:588 [inline] invoke_softirq kernel/softirq.c:428 [inline] __irq_exit_rcu+0xf4/0x1c0 kernel/softirq.c:637 irq_exit_rcu+0x9/0x30 kernel/softirq.c:649 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1043 [inline] sysvec_apic_timer_interrupt+0xa6/0xc0 arch/x86/kernel/apic/apic.c:1043 asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702 Last potentially related work creation: kasan_save_stack+0x3f/0x60 mm/kasan/common.c:47 __kasan_record_aux_stack+0xac/0xc0 mm/kasan/generic.c:541 __call_rcu_common kernel/rcu/tree.c:3106 [inline] call_rcu+0x167/0xa70 kernel/rcu/tree.c:3210 refdst_drop include/net/dst.h:263 [inline] skb_dst_drop include/net/dst.h:275 [inline] nf_ct_frag6_queue net/ipv6/netfilter/nf_conntrack_reasm.c:306 [inline] nf_ct_frag6_gather+0xb9a/0x2080 net/ipv6/netfilter/nf_conntrack_reasm.c:485 ipv6_defrag+0x2c8/0x3c0 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:67 nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] nf_hook_slow+0xc3/0x220 net/netfilter/core.c:626 nf_hook include/linux/netfilter.h:269 [inline] __ip6_local_out+0x6fa/0x800 net/ipv6/output_core.c:143 ip6_local_out+0x26/0x70 net/ipv6/output_core.c:153 ip6_send_skb+0x112/0x230 net/ipv6/ip6_output.c:1959 rawv6_push_pending_frames+0x75c/0x9e0 net/ipv6/raw.c:588 rawv6_sendmsg+0x19c7/0x23c0 net/ipv6/raw.c:926 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x1a6/0x270 net/socket.c:745 sock_write_iter+0x2dd/0x400 net/socket.c:1160 do_iter_readv_writev+0x60a/0x890
--- net/ipv6/ip6_output.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv6/ip6_output.c +2 -0
@@ -1993,6 +1993,7 @@ int ip6_send_skb(struct sk_buff *skb)struct rt6_info *rt = (struct rt6_info *)skb_dst (skb);int err; +rcu_read_lock (); err =ip6_local_out (net, skb->sk, skb);if (err) {if (err >0 )
@@ -2002,6 +2003,7 @@ int ip6_send_skb(struct sk_buff *skb) IPSTATS_MIB_OUTDISCARDS); } +rcu_read_unlock ();return err; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 252/321 ipv6: fix possible UAF in ip6_finish_output2()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit da273b377ae0d9bd255281ed3c2adb228321687b ]
If skb_expand_head() returns NULL, skb has been freed and associated dst/idev could also have been freed.
We need to hold rcu_read_lock() to make sure the dst and associated idev are alive.
--- net/ipv6/ip6_output.c | 4 ++++ 1 file changed, 4 insertions(+)
net/ipv6/ip6_output.c +4 -0
@@ -69,11 +69,15 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff */* Be paranoid, rather than too clever. */ if (unlikely (hh_len >skb_headroom (skb)) && dev->header_ops) { +/* Make sure idev stays alive */ +rcu_read_lock (); skb =skb_expand_head (skb, hh_len);if (!skb) {IP6_INC_STATS (net, idev,IPSTATS_MIB_OUTDISCARDS ); +rcu_read_unlock ();return -ENOMEM ; } +rcu_read_unlock (); } hdr =ipv6_hdr (skb);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 253/321 ipv6: prevent possible UAF in ip6_xmit()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 2d5ff7e339d04622d8282661df36151906d0e1c7 ]
If skb_expand_head() returns NULL, skb has been freed and the associated dst/idev could also have been freed.
We must use rcu_read_lock() to prevent a possible UAF.
--- net/ipv6/ip6_output.c | 4 ++++ 1 file changed, 4 insertions(+)
net/ipv6/ip6_output.c +4 -0
@@ -278,11 +278,15 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, head_room += opt->opt_nflen + opt->opt_flen;if (unlikely (head_room >skb_headroom (skb))) { +/* Make sure idev stays alive */ +rcu_read_lock (); skb =skb_expand_head (skb, head_room);if (!skb) {IP6_INC_STATS (net, idev,IPSTATS_MIB_OUTDISCARDS ); +rcu_read_unlock ();return -ENOBUFS ; } +rcu_read_unlock (); }if (opt) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 254/321 netfilter: flowtable: validate vlan header
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 6ea14ccb60c8ab829349979b22b58a941ec4a3ee ]
Ensure there is sufficient room to access the protocol field of the VLAN header, validate it once before the flowtable lookup.
=====================================================
BUG: KMSAN: uninit-value in nf_flow_offload_inet_hook+0x45a/0x5f0 net/netfilter/nf_flow_table_inet.c:32 nf_flow_offload_inet_hook+0x45a/0x5f0 net/netfilter/nf_flow_table_inet.c:32 nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] nf_hook_slow+0xf4/0x400 net/netfilter/core.c:626 nf_hook_ingress include/linux/netfilter_netdev.h:34 [inline] nf_ingress net/core/dev.c:5440 [inline]
--- net/netfilter/nf_flow_table_inet.c | 3 +++ net/netfilter/nf_flow_table_ip.c | 3 +++ 2 files changed, 6 insertions(+)
net/netfilter/nf_flow_table_inet.c +3 -0
@@ -17,6 +17,9 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,switch (skb->protocol) {case htons (ETH_P_8021Q ): +if (!pskb_may_pull (skb,skb_mac_offset (skb) +sizeof (*veth))) +return NF_ACCEPT ; + veth = (struct vlan_ethhdr *)skb_mac_header (skb); proto = veth->h_vlan_encapsulated_proto;break ;
net/netfilter/nf_flow_table_ip.c +3 -0
@@ -275,6 +275,9 @@ static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto,switch (skb->protocol) {case htons (ETH_P_8021Q ): +if (!pskb_may_pull (skb,skb_mac_offset (skb) +sizeof (*veth))) +return false; + veth = (struct vlan_ethhdr *)skb_mac_header (skb);if (veth->h_vlan_encapsulated_proto == proto) { *offset +=VLAN_HLEN ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 255/321 octeontx2-af: Fix CPT AF register offset calculation
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bharat Bhushan <[email protected]>
[ Upstream commit af688a99eb1fc7ef69774665d61e6be51cea627a ]
Some CPT AF registers are per LF and others are global. Translation of PF/VF local LF slot number to actual LF slot number is required only for accessing perf LF registers. CPT AF global registers access do not require any LF slot number. Also, there is no reason CPT PF/VF to know actual lf's register offset.
Without this fix microcode loading will fail, VFs cannot be created and hardware is not usable.
--- .../ethernet/marvell/octeontx2/af/rvu_cpt.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-)
drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +11 -12
@@ -632,7 +632,9 @@ int rvu_mbox_handler_cpt_inline_ipsec_cfg(struct rvu *rvu,return ret; } -static bool is_valid_offset (struct rvu *rvu,struct cpt_rd_wr_reg_msg *req) +static bool validate_and_update_reg_offset (struct rvu *rvu, +struct cpt_rd_wr_reg_msg *req, +u64 *reg_offset) {u64 offset = req->reg_offset;int blkaddr, num_lfs, lf;
@@ -663,6 +665,11 @@ static bool is_valid_offset(struct rvu *rvu, struct cpt_rd_wr_reg_msg *req)if (lf <0 )return false; +/* Translate local LF's offset to global CPT LF's offset to +* access LFX register. +*/ + *reg_offset = (req->reg_offset &0xFF000 ) + (lf <<3 ); +return true; }else if (!(req->hdr.pcifunc &RVU_PFVF_FUNC_MASK )) {/* Registers that can be accessed from PF */
@@ -697,7 +704,7 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, struct cpt_rd_wr_reg_msg *rsp) {u64 offset = req->reg_offset; -int blkaddr, lf; +int blkaddr; blkaddr =validate_and_get_cpt_blkaddr (req->blkaddr);if (blkaddr <0 )
@@ -708,18 +715,10 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, !is_cpt_vf(rvu, req->hdr.pcifunc))return CPT_AF_ERR_ACCESS_DENIED ; -if (!is_valid_offset (rvu, req)) +if (!validate_and_update_reg_offset (rvu, req, &offset))return CPT_AF_ERR_ACCESS_DENIED ; -/* Translate local LF used by VFs to global CPT LF */ - lf =rvu_get_lf (rvu, &rvu->hw->block[blkaddr], req->hdr.pcifunc, - (offset &0xFFF ) >>3 ); - -/* Translate local LF's offset to global CPT LF's offset */ - offset &=0xFF000 ; - offset += lf <<3 ; - - rsp->reg_offset = offset; + rsp->reg_offset = req->reg_offset; rsp->ret_val = req->ret_val; rsp->is_write = req->is_write;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 256/321 net: xilinx: axienet: Always disable promiscuous mode
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Anderson <[email protected]>
[ Upstream commit 4ae738dfef2c0323752ab81786e2d298c9939321 ]
If promiscuous mode is disabled when there are fewer than four multicast addresses, then it will not be reflected in the hardware. Fix this by always clearing the promiscuous mode flag even when we program multicast addresses.
--- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/xilinx/xilinx_axienet_main.c +4 -0
@@ -429,6 +429,10 @@ static void axienet_set_multicast_list(struct net_device *ndev) }else if (!netdev_mc_empty (ndev)) {struct netdev_hw_addr *ha; + reg =axienet_ior (lp,XAE_FMI_OFFSET ); + reg &= ~XAE_FMI_PM_MASK ; +axienet_iow (lp,XAE_FMI_OFFSET , reg); + i =0 ;netdev_for_each_mc_addr (ha, ndev) {if (i >=XAE_MULTICAST_CAM_TABLE_NUM )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 257/321 net: xilinx: axienet: Fix dangling multicast addresses
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Anderson <[email protected]>
[ Upstream commit 797a68c9de0f5a5447baf4bd3bb9c10a3993435b ]
If a multicast address is removed but there are still some multicast addresses, that address would remain programmed into the frame filter. Fix this by explicitly setting the enable bit for each filter.
--- drivers/net/ethernet/xilinx/xilinx_axienet.h | 1 + .../net/ethernet/xilinx/xilinx_axienet_main.c | 21 ++++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-)
drivers/net/ethernet/xilinx/xilinx_axienet.h +1 -0
@@ -169,6 +169,7 @@#define XAE_UAW0_OFFSET 0x00000700/* Unicast address word 0 */ #define XAE_UAW1_OFFSET 0x00000704/* Unicast address word 1 */ #define XAE_FMI_OFFSET 0x00000708/* Frame Filter Control */ +#define XAE_FFE_OFFSET 0x0000070C/* Frame Filter Enable */ #define XAE_AF0_OFFSET 0x00000710/* Address Filter 0 */ #define XAE_AF1_OFFSET 0x00000714/* Address Filter 1 */
drivers/net/ethernet/xilinx/xilinx_axienet_main.c +9 -12
@@ -411,7 +411,7 @@ static int netdev_set_mac_address(struct net_device *ndev, void *p)*/ static void axienet_set_multicast_list (struct net_device *ndev) { -int i; +int i =0 ;u32 reg, af0reg, af1reg;struct axienet_local *lp =netdev_priv (ndev);
@@ -433,7 +433,6 @@ static void axienet_set_multicast_list(struct net_device *ndev) reg &= ~XAE_FMI_PM_MASK ;axienet_iow (lp,XAE_FMI_OFFSET , reg); - i =0 ;netdev_for_each_mc_addr (ha, ndev) {if (i >=XAE_MULTICAST_CAM_TABLE_NUM )break ;
@@ -452,6 +451,7 @@ static void axienet_set_multicast_list(struct net_device *ndev)axienet_iow (lp,XAE_FMI_OFFSET , reg);axienet_iow (lp,XAE_AF0_OFFSET , af0reg);axienet_iow (lp,XAE_AF1_OFFSET , af1reg); +axienet_iow (lp,XAE_FFE_OFFSET ,1 ); i++; } }else {
@@ -459,18 +459,15 @@ static void axienet_set_multicast_list(struct net_device *ndev) reg &= ~XAE_FMI_PM_MASK ;axienet_iow (lp,XAE_FMI_OFFSET , reg); - -for (i =0 ; i <XAE_MULTICAST_CAM_TABLE_NUM ; i++) { - reg =axienet_ior (lp,XAE_FMI_OFFSET ) &0xFFFFFF00 ; - reg |= i; - -axienet_iow (lp,XAE_FMI_OFFSET , reg); -axienet_iow (lp,XAE_AF0_OFFSET ,0 ); -axienet_iow (lp,XAE_AF1_OFFSET ,0 ); - } -dev_info (&ndev->dev,"Promiscuous mode disabled.\n" ); } + +for (; i <XAE_MULTICAST_CAM_TABLE_NUM ; i++) { + reg =axienet_ior (lp,XAE_FMI_OFFSET ) &0xFFFFFF00 ; + reg |= i; +axienet_iow (lp,XAE_FMI_OFFSET , reg); +axienet_iow (lp,XAE_FFE_OFFSET ,0 ); + } }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 258/321 drm/msm/dpu: dont play tricks with debug macros
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit df24373435f5899a2a98b7d377479c8d4376613b ]
DPU debugging macros need to be converted to a proper drm_debug_* macros, however this is a going an intrusive patch, not suitable for a fix. Wire DPU_DEBUG and DPU_DEBUG_DRIVER to always use DRM_DEBUG_DRIVER to make sure that DPU debugging messages always end up in the drm debug messages and are controlled via the usual drm.debug mask.
I don't think that it is a good idea for a generic DPU_DEBUG macro to be tied to DRM_UT_KMS. It is used to report a debug message from driver, so by default it should go to the DRM_UT_DRIVER channel. While refactoring debug macros later on we might end up with particular messages going to ATOMIC or KMS, but DRIVER should be the default.
Patchwork: https://patchwork.freedesktop.org/patch/606932/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +2 -12
@@ -31,24 +31,14 @@* @fmt: Pointer to format string */ #define DPU_DEBUG (fmt, ...) \ - do { \ - if (drm_debug_enabled(DRM_UT_KMS)) \ - DRM_DEBUG(fmt, ##__VA_ARGS__); \ - else \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) + DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)/** * DPU_DEBUG_DRIVER - macro for hardware driver logging * @fmt: Pointer to format string */ #define DPU_DEBUG_DRIVER (fmt, ...) \ - do { \ - if (drm_debug_enabled(DRM_UT_DRIVER)) \ - DRM_ERROR(fmt, ##__VA_ARGS__); \ - else \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) + DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)#define DPU_ERROR (fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__)#define DPU_ERROR_RATELIMITED (fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 259/321 drm/msm/dp: fix the max supported bpp logic
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abhinav Kumar <[email protected]>
[ Upstream commit d19d5b8d8f6dab942ce5ddbcf34bf7275e778250 ]
Fix the dp_panel_get_supported_bpp() API to return the minimum supported bpp correctly for relevant cases and use this API to correct the behavior of DP driver which hard-codes the max supported bpp to 30.
This is incorrect because the number of lanes and max data rate supported by the lanes need to be taken into account.
Replace the hardcoded limit with the appropriate math which accounts for the accurate number of lanes and max data rate.
changes in v2:
- Fix the dp_panel_get_supported_bpp() and use it
- Drop the max_t usage as dp_panel_get_supported_bpp() already returns the min_bpp correctly now
changes in v3:
- replace min_t with just min as all params are u32
Patchwork: https://patchwork.freedesktop.org/patch/607073/
--- drivers/gpu/drm/msm/dp/dp_panel.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
drivers/gpu/drm/msm/dp/dp_panel.c +10 -9
@@ -113,22 +113,22 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)static u32 dp_panel_get_supported_bpp (struct dp_panel *dp_panel,u32 mode_edid_bpp,u32 mode_pclk_khz) { -struct dp_link_info *link_info; +const struct dp_link_info *link_info;const u32 max_supported_bpp =30 , min_supported_bpp =18 ; -u32 bpp =0 , data_rate_khz =0 ; +u32 bpp, data_rate_khz; - bpp =min_t (u32, mode_edid_bpp, max_supported_bpp); + bpp =min (mode_edid_bpp, max_supported_bpp); link_info = &dp_panel->link_info; data_rate_khz = link_info->num_lanes * link_info->rate *8 ; -while (bpp > min_supported_bpp) { +do {if (mode_pclk_khz * bpp <= data_rate_khz) -break ; +return bpp; bpp -=6 ; - } + }while (bpp > min_supported_bpp); -return bpp; +return min_supported_bpp; } static int dp_panel_update_modes(struct drm_connector *connector,
@@ -421,8 +421,9 @@ int dp_panel_init_panel_info(struct dp_panel *dp_panel) drm_mode->clock);drm_dbg_dp (panel->drm_dev,"bpp = %d\n" , dp_panel->dp_mode.bpp); - dp_panel->dp_mode.bpp =max_t (u32,18 , -min_t (u32, dp_panel->dp_mode.bpp,30 )); + dp_panel->dp_mode.bpp =dp_panel_get_mode_bpp (dp_panel, dp_panel->dp_mode.bpp, + dp_panel->dp_mode.drm_mode.clock); +drm_dbg_dp (panel->drm_dev,"updated bpp = %d\n" , dp_panel->dp_mode.bpp);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 260/321 drm/msm/dp: reset the link phy params before link training
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abhinav Kumar <[email protected]>
[ Upstream commit 319aca883bfa1b85ee08411541b51b9a934ac858 ]
Before re-starting link training reset the link phy params namely the pre-emphasis and voltage swing levels otherwise the next link training begins at the previously cached levels which can result in link training failures.
Patchwork: https://patchwork.freedesktop.org/patch/605946/
--- drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/msm/dp/dp_ctrl.c +2 -0
@@ -1248,6 +1248,8 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, link_info.rate = ctrl->link->link_params.rate; link_info.capabilities =DP_LINK_CAP_ENHANCED_FRAMING ; +dp_link_reset_phy_params_vx_px (ctrl->link); +dp_aux_link_configure (ctrl->aux, &link_info);if (drm_dp_max_downspread (dpcd))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 261/321 drm/msm/dpu: cleanup FB if dpu_format_populate_layout fails
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit bfa1a6283be390947d3649c482e5167186a37016 ]
If the dpu_format_populate_layout() fails, then FB is prepared, but not cleaned up. This ends up leaking the pin_count on the GEM object and causes a splat during DRM file closure:
msm_obj->pin_count
WARNING: CPU: 2 PID: 569 at drivers/gpu/drm/msm/msm_gem.c:121 update_lru_locked+0xc4/0xcc [...] Call trace: update_lru_locked+0xc4/0xcc put_pages+0xac/0x100 msm_gem_free_object+0x138/0x180 drm_gem_object_free+0x1c/0x30 drm_gem_object_handle_put_unlocked+0x108/0x10c drm_gem_object_release_handle+0x58/0x70 idr_for_each+0x68/0xec drm_gem_release+0x28/0x40 drm_file_free+0x174/0x234 drm_release+0xb0/0x160 __fput+0xc0/0x2c8 __fput_sync+0x50/0x5c __arm64_sys_close+0x38/0x7c invoke_syscall+0x48/0x118 el0_svc_common.constprop.0+0x40/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x4c/0x120 el0t_64_sync_handler+0x100/0x12c el0t_64_sync+0x190/0x194 irq event stamp: 129818 hardirqs last enabled at (129817): [<ffffa5f6d953fcc0>] console_unlock+0x118/0x124 hardirqs last disabled at (129818): [<ffffa5f6da7dcf04>] el1_dbg+0x24/0x8c softirqs last enabled at (129808): [<ffffa5f6d94afc18>] handle_softirqs+0x4c8/0x4e8 softirqs last disabled at (129785): [<ffffa5f6d94105e4>] __do_softirq+0x14/0x20
Patchwork: https://patchwork.freedesktop.org/patch/600714/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +3 -0
@@ -889,6 +889,9 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, new_state->fb, &layout);if (ret) {DPU_ERROR_PLANE (pdpu,"failed to get format layout, %d\n" , ret); +if (pstate->aspace) +msm_framebuffer_cleanup (new_state->fb, pstate->aspace, + pstate->needs_dirtyfb);return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 262/321 mmc: mmc_test: Fix NULL dereference on allocation failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit a1e627af32ed60713941cbfc8075d44cad07f6dd ]
If the "test->highmem = alloc_pages()" allocation fails then calling __free_pages(test->highmem) will result in a NULL dereference. Also change the error code to -ENOMEM instead of returning success.
--- drivers/mmc/core/mmc_test.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/mmc/core/mmc_test.c +5 -4
@@ -3109,13 +3109,13 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf, test->buffer =kzalloc (BUFFER_SIZE ,GFP_KERNEL );#ifdef CONFIG_HIGHMEM test->highmem =alloc_pages (GFP_KERNEL | __GFP_HIGHMEM,BUFFER_ORDER ); +if (!test->highmem) { + count = -ENOMEM ; + goto free_test_buffer; + }#endif -#ifdef CONFIG_HIGHMEM -if (test->buffer && test->highmem) { -#else if (test->buffer) { -#endif mutex_lock (&mmc_test_lock);mmc_test_run (test, testcase);mutex_unlock (&mmc_test_lock);
@@ -3123,6 +3123,7 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,#ifdef CONFIG_HIGHMEM __free_pages (test->highmem,BUFFER_ORDER ); +free_test_buffer:#endif kfree (test->buffer);kfree (test);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 263/321 Bluetooth: MGMT: Add error handling to pair_device()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Griffin Kroah-Hartman <[email protected]>
commit 538fd3921afac97158d4177139a0ad39f056dbb2 upstream.
hci_conn_params_add() never checks for a NULL value and could lead to a NULL pointer dereference causing a crash.
Fixed by adding error handling in the function.
--- net/bluetooth/mgmt.c | 4 ++++ 1 file changed, 4 insertions(+)
net/bluetooth/mgmt.c +4 -0
@@ -3524,6 +3524,10 @@ static int pair_device(struct sock *sk,* will be kept and this function does nothing. */ p =hci_conn_params_add (hdev, &cp->addr.bdaddr, addr_type); +if (!p) { + err = -EIO ; + goto unlock; + }if (p->auto_connect ==HCI_AUTO_CONN_EXPLICIT ) p->auto_connect =HCI_AUTO_CONN_DISABLED ;
Greg Kroah-Hartman
maintainerPATCH 264/321 scsi: core: Fix the return value of scsi_logical_block_count()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chaotian Jing <[email protected]>
commit f03e94f23b04c2b71c0044c1534921b3975ef10c upstream.
scsi_logical_block_count() should return the block count of a given SCSI command. The original implementation ended up shifting twice, leading to an incorrect count being returned. Fix the conversion between bytes and logical blocks.
--- include/scsi/scsi_cmnd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/scsi/scsi_cmnd.h +1 -1
@@ -228,7 +228,7 @@ static inline sector_t scsi_get_lba(strustatic inline unsigned int scsi_logical_block_count (struct scsi_cmnd *scmd) { -unsigned int shift =ilog2 (scmd->device->sector_size) -SECTOR_SHIFT ; +unsigned int shift =ilog2 (scmd->device->sector_size);return blk_rq_bytes (scsi_cmd_to_rq (scmd)) >> shift; }
Greg Kroah-Hartman
maintainerPATCH 265/321 ksmbd: the buffer of smb2 query dir response has at least 1 byte
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
commit ce61b605a00502c59311d0a4b1f58d62b48272d0 upstream.
When STATUS_NO_MORE_FILES status is set to smb2 query dir response, ->StructureSize is set to 9, which mean buffer has 1 byte. This issue occurs because ->Buffer[1] in smb2_query_directory_rsp to flex-array.
--- fs/smb/server/smb2pdu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/smb/server/smb2pdu.c +2 -1
@@ -4169,7 +4169,8 @@ int smb2_query_dir(struct ksmbd_work *wo rsp->OutputBufferLength =cpu_to_le32 (0 ); rsp->Buffer[0 ] =0 ; rc =ksmbd_iov_pin_rsp (work, (void *)rsp, -sizeof (struct smb2_query_directory_rsp )); + offsetof(struct smb2_query_directory_rsp , Buffer) + +1 );if (rc) goto err_out; }else {
Greg Kroah-Hartman
maintainerPATCH 266/321 drm/amdgpu: Validate TA binary size
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Candice Li <[email protected]>
commit c99769bceab4ecb6a067b9af11f9db281eea3e2a upstream.
Add TA binary size validation to avoid OOB write.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +3 -0
@@ -148,6 +148,9 @@ static ssize_t ta_if_load_debugfs_write(if (ret)return -EINVAL ; +if (ta_bin_len >PSP_1_MEG ) +return -EINVAL ; + copy_pos +=sizeof (uint32_t ); ta_bin =kzalloc (ta_bin_len,GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 267/321 MIPS: Loongson64: Set timer mode in cpu-probe
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiaxun Yang <[email protected]>
commit 1cb6ab446424649f03c82334634360c2e3043684 upstream.
Loongson64 C and G processors have EXTIMER feature which is conflicting with CP0 counter.
Although the processor resets in EXTIMER disabled & INTIMER enabled mode, which is compatible with MIPS CP0 compare, firmware may attempt to enable EXTIMER and interfere CP0 compare.
Set timer mode back to MIPS compatible mode to fix booting on systems with such firmware before we have an actual driver for EXTIMER.
--- arch/mips/kernel/cpu-probe.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/mips/kernel/cpu-probe.c +4 -0
@@ -1723,12 +1723,16 @@ static inline void cpu_probe_loongson(st c->ases |= (MIPS_ASE_LOONGSON_MMI |MIPS_ASE_LOONGSON_CAM |MIPS_ASE_LOONGSON_EXT |MIPS_ASE_LOONGSON_EXT2 ); c->ases &= ~MIPS_ASE_VZ ;/* VZ of Loongson-3A2000/3000 is incomplete */ +change_c0_config6 (LOONGSON_CONF6_EXTIMER |LOONGSON_CONF6_INTIMER , +LOONGSON_CONF6_INTIMER );break ;case PRID_IMP_LOONGSON_64G : __cpu_name[cpu] ="ICT Loongson-3" ;set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R2 );decode_cpucfg (c); +change_c0_config6 (LOONGSON_CONF6_EXTIMER |LOONGSON_CONF6_INTIMER , +LOONGSON_CONF6_INTIMER );break ;default :panic ("Unknown Loongson Processor ID!" );