Re: [PATCH 6.1.y] rcu-tasks: Fix access non-existent percpu rtpcp variable in rcu_tasks_need_gpcb()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[ Sasha's backport helper bot ]

Hi,

The upstream commit SHA1 provided is correct: fd70e9f1d85f5323096ad313ba73f5fe3d15ea41

WARNING: Author mismatch between patch and upstream commit:
Backport author: Xiangyu Chen <xiangyu.chen@xxxxxxxxxxxxxxxxx>
Commit author: Zqiang <qiang.zhang1211@xxxxxxxxx>


Status in newer kernel trees:
6.12.y | Present (exact SHA1)
6.11.y | Present (different SHA1: 05095271a4fb)
6.6.y | Present (different SHA1: b3b2431ed27f)
6.1.y | Not found

Note: The patch differs from the upstream commit:
---
--- -	2024-11-27 08:44:48.162519786 -0500
+++ /tmp/tmp.BM83GdWj4t	2024-11-27 08:44:48.157166722 -0500
@@ -1,3 +1,5 @@
+[ Upstream commit fd70e9f1d85f5323096ad313ba73f5fe3d15ea41 ]
+
 For kernels built with CONFIG_FORCE_NR_CPUS=y, the nr_cpu_ids is
 defined as NR_CPUS instead of the number of possible cpus, this
 will cause the following system panic:
@@ -40,65 +42,68 @@
 Reported-by: Zhixu Liu <zhixu.liu@xxxxxxxxx>
 Signed-off-by: Zqiang <qiang.zhang1211@xxxxxxxxx>
 Signed-off-by: Neeraj Upadhyay <neeraj.upadhyay@xxxxxxxxxx>
+Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
+[Xiangyu: BP to fix CVE:CVE-2024-49926, minor conflict resolution]
+Signed-off-by: Xiangyu Chen <xiangyu.chen@xxxxxxxxxxxxx>
 ---
  kernel/rcu/tasks.h | 82 ++++++++++++++++++++++++++++++----------------
- 1 file changed, 53 insertions(+), 29 deletions(-)
+ 1 file changed, 54 insertions(+), 28 deletions(-)
 
 diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
-index 4bc038bcc0169..72d564c84499a 100644
+index bb6b037ef30f..46b207eac171 100644
 --- a/kernel/rcu/tasks.h
 +++ b/kernel/rcu/tasks.h
-@@ -34,6 +34,7 @@ typedef void (*postgp_func_t)(struct rcu_tasks *rtp);
+@@ -31,6 +31,7 @@ typedef void (*postgp_func_t)(struct rcu_tasks *rtp);
+  * @barrier_q_head: RCU callback for barrier operation.
   * @rtp_blkd_tasks: List of tasks blocked as readers.
-  * @rtp_exit_list: List of tasks in the latter portion of do_exit().
   * @cpu: CPU number corresponding to this entry.
 + * @index: Index of this CPU in rtpcp_array of the rcu_tasks structure.
   * @rtpp: Pointer to the rcu_tasks structure.
   */
  struct rcu_tasks_percpu {
-@@ -49,6 +50,7 @@ struct rcu_tasks_percpu {
+@@ -43,6 +44,7 @@ struct rcu_tasks_percpu {
+ 	struct rcu_head barrier_q_head;
  	struct list_head rtp_blkd_tasks;
- 	struct list_head rtp_exit_list;
  	int cpu;
 +	int index;
  	struct rcu_tasks *rtpp;
  };
  
-@@ -76,6 +78,7 @@ struct rcu_tasks_percpu {
+@@ -68,6 +70,7 @@ struct rcu_tasks_percpu {
+  * @postgp_func: This flavor's post-grace-period function (optional).
   * @call_func: This flavor's call_rcu()-equivalent function.
-  * @wait_state: Task state for synchronous grace-period waits (default TASK_UNINTERRUPTIBLE).
   * @rtpcpu: This flavor's rcu_tasks_percpu structure.
 + * @rtpcp_array: Array of pointers to rcu_tasks_percpu structure of CPUs in cpu_possible_mask.
   * @percpu_enqueue_shift: Shift down CPU ID this much when enqueuing callbacks.
   * @percpu_enqueue_lim: Number of per-CPU callback queues in use for enqueuing.
   * @percpu_dequeue_lim: Number of per-CPU callback queues in use for dequeuing.
-@@ -110,6 +113,7 @@ struct rcu_tasks {
+@@ -100,6 +103,7 @@ struct rcu_tasks {
+ 	postgp_func_t postgp_func;
  	call_rcu_func_t call_func;
- 	unsigned int wait_state;
  	struct rcu_tasks_percpu __percpu *rtpcpu;
 +	struct rcu_tasks_percpu **rtpcp_array;
  	int percpu_enqueue_shift;
  	int percpu_enqueue_lim;
  	int percpu_dequeue_lim;
-@@ -182,6 +186,8 @@ module_param(rcu_task_collapse_lim, int, 0444);
- static int rcu_task_lazy_lim __read_mostly = 32;
- module_param(rcu_task_lazy_lim, int, 0444);
+@@ -164,6 +168,8 @@ module_param(rcu_task_contend_lim, int, 0444);
+ static int rcu_task_collapse_lim __read_mostly = 10;
+ module_param(rcu_task_collapse_lim, int, 0444);
  
 +static int rcu_task_cpu_ids;
 +
  /* RCU tasks grace-period state for debugging. */
  #define RTGS_INIT		 0
  #define RTGS_WAIT_WAIT_CBS	 1
-@@ -245,6 +251,8 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
- 	int cpu;
+@@ -228,6 +234,8 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
+ 	unsigned long flags;
  	int lim;
  	int shift;
 +	int maxcpu;
 +	int index = 0;
  
+ 	raw_spin_lock_irqsave(&rtp->cbs_gbl_lock, flags);
  	if (rcu_task_enqueue_lim < 0) {
- 		rcu_task_enqueue_lim = 1;
-@@ -254,14 +262,9 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
+@@ -238,14 +246,9 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
  	}
  	lim = rcu_task_enqueue_lim;
  
@@ -116,7 +121,7 @@
  	for_each_possible_cpu(cpu) {
  		struct rcu_tasks_percpu *rtpcp = per_cpu_ptr(rtp->rtpcpu, cpu);
  
-@@ -273,14 +276,29 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
+@@ -258,16 +261,33 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
  		INIT_WORK(&rtpcp->rtp_work, rcu_tasks_invoke_cbs_wq);
  		rtpcp->cpu = cpu;
  		rtpcp->rtpp = rtp;
@@ -125,13 +130,15 @@
 +		index++;
  		if (!rtpcp->rtp_blkd_tasks.next)
  			INIT_LIST_HEAD(&rtpcp->rtp_blkd_tasks);
- 		if (!rtpcp->rtp_exit_list.next)
- 			INIT_LIST_HEAD(&rtpcp->rtp_exit_list);
+ 		raw_spin_unlock_rcu_node(rtpcp); // irqs remain disabled.
 +		maxcpu = cpu;
  	}
+ 	raw_spin_unlock_irqrestore(&rtp->cbs_gbl_lock, flags);
  
--	pr_info("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d.\n", rtp->name,
--			data_race(rtp->percpu_enqueue_shift), data_race(rtp->percpu_enqueue_lim), rcu_task_cb_adjust);
+ 	if (rcu_task_cb_adjust)
+ 		pr_info("%s: Setting adjustable number of callback queues.\n", __func__);
+ 
+-	pr_info("%s: Setting shift to %d and lim to %d.\n", __func__, data_race(rtp->percpu_enqueue_shift), data_race(rtp->percpu_enqueue_lim));
 +	rcu_task_cpu_ids = maxcpu + 1;
 +	if (lim > rcu_task_cpu_ids)
 +		lim = rcu_task_cpu_ids;
@@ -145,10 +152,11 @@
 +	pr_info("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d rcu_task_cpu_ids=%d.\n",
 +			rtp->name, data_race(rtp->percpu_enqueue_shift), data_race(rtp->percpu_enqueue_lim),
 +			rcu_task_cb_adjust, rcu_task_cpu_ids);
++
  }
  
- // Compute wakeup time for lazy callback timer.
-@@ -348,7 +366,7 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
+ // IRQ-work handler that does deferred wakeup for call_rcu_tasks_generic().
+@@ -307,7 +327,7 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
  			rtpcp->rtp_n_lock_retries = 0;
  		}
  		if (rcu_task_cb_adjust && ++rtpcp->rtp_n_lock_retries > rcu_task_contend_lim &&
@@ -156,8 +164,8 @@
 +		    READ_ONCE(rtp->percpu_enqueue_lim) != rcu_task_cpu_ids)
  			needadjust = true;  // Defer adjustment to avoid deadlock.
  	}
- 	// Queuing callbacks before initialization not yet supported.
-@@ -368,10 +386,10 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
+ 	if (!rcu_segcblist_is_enabled(&rtpcp->cblist)) {
+@@ -320,10 +340,10 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
  	raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
  	if (unlikely(needadjust)) {
  		raw_spin_lock_irqsave(&rtp->cbs_gbl_lock, flags);
@@ -171,16 +179,16 @@
  			pr_info("Switching %s to per-CPU callback queuing.\n", rtp->name);
  		}
  		raw_spin_unlock_irqrestore(&rtp->cbs_gbl_lock, flags);
-@@ -444,6 +462,8 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+@@ -394,6 +414,8 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+ 	int needgpcb = 0;
  
- 	dequeue_limit = smp_load_acquire(&rtp->percpu_dequeue_lim);
- 	for (cpu = 0; cpu < dequeue_limit; cpu++) {
+ 	for (cpu = 0; cpu < smp_load_acquire(&rtp->percpu_dequeue_lim); cpu++) {
 +		if (!cpu_possible(cpu))
 +			continue;
  		struct rcu_tasks_percpu *rtpcp = per_cpu_ptr(rtp->rtpcpu, cpu);
  
  		/* Advance and accelerate any new callbacks. */
-@@ -481,7 +501,7 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+@@ -426,7 +448,7 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
  	if (rcu_task_cb_adjust && ncbs <= rcu_task_collapse_lim) {
  		raw_spin_lock_irqsave(&rtp->cbs_gbl_lock, flags);
  		if (rtp->percpu_enqueue_lim > 1) {
@@ -189,7 +197,7 @@
  			smp_store_release(&rtp->percpu_enqueue_lim, 1);
  			rtp->percpu_dequeue_gpseq = get_state_synchronize_rcu();
  			gpdone = false;
-@@ -496,7 +516,9 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+@@ -441,7 +463,9 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
  			pr_info("Completing switch %s to CPU-0 callback queuing.\n", rtp->name);
  		}
  		if (rtp->percpu_dequeue_lim == 1) {
@@ -200,7 +208,7 @@
  				struct rcu_tasks_percpu *rtpcp = per_cpu_ptr(rtp->rtpcpu, cpu);
  
  				WARN_ON_ONCE(rcu_segcblist_n_cbs(&rtpcp->cblist));
-@@ -511,30 +533,32 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+@@ -456,30 +480,32 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
  // Advance callbacks and invoke any that are ready.
  static void rcu_tasks_invoke_cbs(struct rcu_tasks *rtp, struct rcu_tasks_percpu *rtpcp)
  {
@@ -246,3 +254,6 @@
  		return;
  	raw_spin_lock_irqsave_rcu_node(rtpcp, flags);
  	rcu_segcblist_advance(&rtpcp->cblist, rcu_seq_current(&rtp->tasks_gp_seq));
+-- 
+2.43.0
+
---

Results of testing on various branches:

| Branch                    | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-6.1.y        |  Success    |  Success   |




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux