Unverified Commit 043514c5 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!9642 CVE-2024-38582

Merge Pull Request from: @ci-robot 
 
PR sync from: Yifan Qiao <qiaoyifan4@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/GGVMXZ65XDFD6OQVCXSDZJ32NWFTUPR6/ 
Ryusuke Konishi (2):
  nilfs2: fix unexpected freezing of nilfs_segctor_sync()
  nilfs2: fix potential hang in nilfs_detach_log_writer()


-- 
2.39.2
 
https://gitee.com/src-openeuler/kernel/issues/IA6SGE 
 
Link:https://gitee.com/openeuler/kernel/pulls/9642

 

Reviewed-by: default avatarZhang Peng <zhangpeng362@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 57a94f68 a92b6a7e
Loading
Loading
Loading
Loading
+31 −7
Original line number Diff line number Diff line
@@ -2209,19 +2209,36 @@ static int nilfs_segctor_sync(struct nilfs_sc_info *sci)
	struct nilfs_segctor_wait_request wait_req;
	int err = 0;

	spin_lock(&sci->sc_state_lock);
	init_wait(&wait_req.wq);
	wait_req.err = 0;
	atomic_set(&wait_req.done, 0);
	init_waitqueue_entry(&wait_req.wq, current);

	/*
	 * To prevent a race issue where completion notifications from the
	 * log writer thread are missed, increment the request sequence count
	 * "sc_seq_request" and insert a wait queue entry using the current
	 * sequence number into the "sc_wait_request" queue at the same time
	 * within the lock section of "sc_state_lock".
	 */
	spin_lock(&sci->sc_state_lock);
	wait_req.seq = ++sci->sc_seq_request;
	add_wait_queue(&sci->sc_wait_request, &wait_req.wq);
	spin_unlock(&sci->sc_state_lock);

	init_waitqueue_entry(&wait_req.wq, current);
	add_wait_queue(&sci->sc_wait_request, &wait_req.wq);
	set_current_state(TASK_INTERRUPTIBLE);
	wake_up(&sci->sc_wait_daemon);

	for (;;) {
		set_current_state(TASK_INTERRUPTIBLE);

		/*
		 * Synchronize only while the log writer thread is alive.
		 * Leave flushing out after the log writer thread exits to
		 * the cleanup work in nilfs_segctor_destroy().
		 */
		if (!sci->sc_task)
			break;

		if (atomic_read(&wait_req.done)) {
			err = wait_req.err;
			break;
@@ -2237,7 +2254,7 @@ static int nilfs_segctor_sync(struct nilfs_sc_info *sci)
	return err;
}

static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)
static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err, bool force)
{
	struct nilfs_segctor_wait_request *wrq, *n;
	unsigned long flags;
@@ -2245,7 +2262,7 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)
	spin_lock_irqsave(&sci->sc_wait_request.lock, flags);
	list_for_each_entry_safe(wrq, n, &sci->sc_wait_request.head, wq.entry) {
		if (!atomic_read(&wrq->done) &&
		    nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq)) {
		    (force || nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq))) {
			wrq->err = err;
			atomic_set(&wrq->done, 1);
		}
@@ -2383,7 +2400,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err)
	if (mode == SC_LSEG_SR) {
		sci->sc_state &= ~NILFS_SEGCTOR_COMMIT;
		sci->sc_seq_done = sci->sc_seq_accepted;
		nilfs_segctor_wakeup(sci, err);
		nilfs_segctor_wakeup(sci, err, false);
		sci->sc_flush_request = 0;
	} else {
		if (mode == SC_FLUSH_FILE)
@@ -2765,6 +2782,13 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
		|| sci->sc_seq_request != sci->sc_seq_done);
	spin_unlock(&sci->sc_state_lock);

	/*
	 * Forcibly wake up tasks waiting in nilfs_segctor_sync(), which can
	 * be called from delayed iput() via nilfs_evict_inode() and can race
	 * with the above log writer thread termination.
	 */
	nilfs_segctor_wakeup(sci, 0, true);

	if (flush_work(&sci->sc_iput_work))
		flag = true;