Unverified Commit 913a5043 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!9872 CVE-2024-38570

Merge Pull Request from: @ci-robot 
 
PR sync from: Zeng Heng <zengheng4@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/E6BWRJVPK65KYGZ6LDYSIE6TQLH676X3/ 
Andreas Gruenbacher (2):
  gfs2: Rename sd_{ glock => kill }_wait
  gfs2: Fix potential glock use-after-free on unmount


--
2.25.1
 
https://gitee.com/src-openeuler/kernel/issues/IA6SA1 
 
Link:https://gitee.com/openeuler/kernel/pulls/9872

 

Reviewed-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
parents 6d5ab00d 8fc4bbb1
Loading
Loading
Loading
Loading
+37 −8
Original line number Diff line number Diff line
@@ -159,17 +159,44 @@ static bool glock_blocked_by_withdraw(struct gfs2_glock *gl)
	return true;
}

void gfs2_glock_free(struct gfs2_glock *gl)
static void __gfs2_glock_free(struct gfs2_glock *gl)
{
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

	gfs2_glock_assert_withdraw(gl, atomic_read(&gl->gl_revokes) == 0);
	rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms);
	smp_mb();
	wake_up_glock(gl);
	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
}

void gfs2_glock_free(struct gfs2_glock *gl) {
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

	__gfs2_glock_free(gl);
	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
		wake_up(&sdp->sd_glock_wait);
		wake_up(&sdp->sd_kill_wait);
}

void gfs2_glock_free_later(struct gfs2_glock *gl) {
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

	spin_lock(&lru_lock);
	list_add(&gl->gl_lru, &sdp->sd_dead_glocks);
	spin_unlock(&lru_lock);
	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
		wake_up(&sdp->sd_kill_wait);
}

static void gfs2_free_dead_glocks(struct gfs2_sbd *sdp)
{
	struct list_head *list = &sdp->sd_dead_glocks;

	while(!list_empty(list)) {
		struct gfs2_glock *gl;

		gl = list_first_entry(list, struct gfs2_glock, gl_lru);
		list_del_init(&gl->gl_lru);
		__gfs2_glock_free(gl);
	}
}

/**
@@ -1097,7 +1124,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
	kfree(gl->gl_lksb.sb_lvbptr);
	kmem_cache_free(cachep, gl);
	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
		wake_up(&sdp->sd_glock_wait);
		wake_up(&sdp->sd_kill_wait);

out:
	return ret;
@@ -2008,9 +2035,11 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
{
	set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
	flush_workqueue(glock_workqueue);
	gfs2_lm_unmount(sdp);
	gfs2_free_dead_glocks(sdp);
	glock_hash_walk(clear_glock, sdp);
	flush_workqueue(glock_workqueue);
	wait_event_timeout(sdp->sd_glock_wait,
	wait_event_timeout(sdp->sd_kill_wait,
			   atomic_read(&sdp->sd_glock_disposal) == 0,
			   HZ * 600);
	glock_hash_walk(dump_glock_func, sdp);
+1 −0
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ extern void gfs2_glock_finish_truncate(struct gfs2_inode *ip);
extern void gfs2_glock_thaw(struct gfs2_sbd *sdp);
extern void gfs2_glock_add_to_lru(struct gfs2_glock *gl);
extern void gfs2_glock_free(struct gfs2_glock *gl);
void gfs2_glock_free_later(struct gfs2_glock *gl);

extern int __init gfs2_glock_init(void);
extern void gfs2_glock_exit(void);
+2 −1
Original line number Diff line number Diff line
@@ -741,7 +741,7 @@ struct gfs2_sbd {
	struct gfs2_glock *sd_rename_gl;
	struct gfs2_glock *sd_freeze_gl;
	struct work_struct sd_freeze_work;
	wait_queue_head_t sd_glock_wait;
	wait_queue_head_t sd_kill_wait;
	wait_queue_head_t sd_async_glock_wait;
	atomic_t sd_glock_disposal;
	struct completion sd_locking_init;
@@ -863,6 +863,7 @@ struct gfs2_sbd {
	struct gfs2_holder sd_freeze_gh;
	atomic_t sd_freeze_state;
	struct mutex sd_freeze_mutex;
	struct list_head sd_dead_glocks;

	char sd_fsname[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2];
	char sd_table_name[GFS2_FSNAME_LEN];
+12 −2
Original line number Diff line number Diff line
@@ -118,6 +118,11 @@ static void gdlm_ast(void *arg)
	struct gfs2_glock *gl = arg;
	unsigned ret = gl->gl_state;

	/* If the glock is dead, we only react to a dlm_unlock() reply. */
	if (__lockref_is_dead(&gl->gl_lockref) &&
	    gl->gl_lksb.sb_status != -DLM_EUNLOCK)
		return;

	gfs2_update_reply_times(gl);
	BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);

@@ -168,6 +173,9 @@ static void gdlm_bast(void *arg, int mode)
{
	struct gfs2_glock *gl = arg;

	if (__lockref_is_dead(&gl->gl_lockref))
		return;

	switch (mode) {
	case DLM_LOCK_EX:
		gfs2_glock_cb(gl, LM_ST_UNLOCKED);
@@ -286,6 +294,8 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
	int error;

	BUG_ON(!__lockref_is_dead(&gl->gl_lockref));

	if (gl->gl_lksb.sb_lkid == 0) {
		gfs2_glock_free(gl);
		return;
@@ -305,7 +315,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl)

	if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
	    !gl->gl_lksb.sb_lvbptr) {
		gfs2_glock_free(gl);
		gfs2_glock_free_later(gl);
		return;
	}

+3 −2
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
	set_bit(SDF_NOJOURNALID, &sdp->sd_flags);
	gfs2_tune_init(&sdp->sd_tune);

	init_waitqueue_head(&sdp->sd_glock_wait);
	init_waitqueue_head(&sdp->sd_kill_wait);
	init_waitqueue_head(&sdp->sd_async_glock_wait);
	atomic_set(&sdp->sd_glock_disposal, 0);
	init_completion(&sdp->sd_locking_init);
@@ -141,6 +141,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
	init_waitqueue_head(&sdp->sd_log_flush_wait);
	atomic_set(&sdp->sd_freeze_state, SFS_UNFROZEN);
	mutex_init(&sdp->sd_freeze_mutex);
	INIT_LIST_HEAD(&sdp->sd_dead_glocks);

	return sdp;

Loading