Skip to content

Commit 61bb4a1

Browse files
committed
ext4: fix possible UAF when remounting r/o a mmp-protected file system
After commit 618f003 ("ext4: fix memory leak in ext4_fill_super"), after the file system is remounted read-only, there is a race where the kmmpd thread can exit, causing sbi->s_mmp_tsk to point at freed memory, which the call to ext4_stop_mmpd() can trip over. Fix this by only allowing kmmpd() to exit when it is stopped via ext4_stop_mmpd(). Link: https://lore.kernel.org/r/20210707002433.3719773-1-tytso@mit.edu Reported-by: Ye Bin <yebin10@huawei.com> Bug-Report-Link: <20210629143603.2166962-1-yebin10@huawei.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Jan Kara <jack@suse.cz>
1 parent cd84bbb commit 61bb4a1

2 files changed

Lines changed: 20 additions & 17 deletions

File tree

fs/ext4/mmp.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,12 @@ static int kmmpd(void *data)
156156
memcpy(mmp->mmp_nodename, init_utsname()->nodename,
157157
sizeof(mmp->mmp_nodename));
158158

159-
while (!kthread_should_stop()) {
159+
while (!kthread_should_stop() && !sb_rdonly(sb)) {
160+
if (!ext4_has_feature_mmp(sb)) {
161+
ext4_warning(sb, "kmmpd being stopped since MMP feature"
162+
" has been disabled.");
163+
goto wait_to_exit;
164+
}
160165
if (++seq > EXT4_MMP_SEQ_MAX)
161166
seq = 1;
162167

@@ -177,16 +182,6 @@ static int kmmpd(void *data)
177182
failed_writes++;
178183
}
179184

180-
if (!(le32_to_cpu(es->s_feature_incompat) &
181-
EXT4_FEATURE_INCOMPAT_MMP)) {
182-
ext4_warning(sb, "kmmpd being stopped since MMP feature"
183-
" has been disabled.");
184-
goto exit_thread;
185-
}
186-
187-
if (sb_rdonly(sb))
188-
break;
189-
190185
diff = jiffies - last_update_time;
191186
if (diff < mmp_update_interval * HZ)
192187
schedule_timeout_interruptible(mmp_update_interval *
@@ -207,7 +202,7 @@ static int kmmpd(void *data)
207202
ext4_error_err(sb, -retval,
208203
"error reading MMP data: %d",
209204
retval);
210-
goto exit_thread;
205+
goto wait_to_exit;
211206
}
212207

213208
mmp_check = (struct mmp_struct *)(bh_check->b_data);
@@ -221,7 +216,7 @@ static int kmmpd(void *data)
221216
ext4_error_err(sb, EBUSY, "abort");
222217
put_bh(bh_check);
223218
retval = -EBUSY;
224-
goto exit_thread;
219+
goto wait_to_exit;
225220
}
226221
put_bh(bh_check);
227222
}
@@ -244,7 +239,13 @@ static int kmmpd(void *data)
244239

245240
retval = write_mmp_block(sb, bh);
246241

247-
exit_thread:
242+
wait_to_exit:
243+
while (!kthread_should_stop()) {
244+
set_current_state(TASK_INTERRUPTIBLE);
245+
if (!kthread_should_stop())
246+
schedule();
247+
}
248+
set_current_state(TASK_RUNNING);
248249
return retval;
249250
}
250251

@@ -391,5 +392,3 @@ int ext4_multi_mount_protect(struct super_block *sb,
391392
brelse(bh);
392393
return 1;
393394
}
394-
395-

fs/ext4/super.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5993,7 +5993,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
59935993
*/
59945994
ext4_mark_recovery_complete(sb, es);
59955995
}
5996-
ext4_stop_mmpd(sbi);
59975996
} else {
59985997
/* Make sure we can mount this feature set readwrite */
59995998
if (ext4_has_feature_readonly(sb) ||
@@ -6107,6 +6106,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
61076106
if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
61086107
ext4_release_system_zone(sb);
61096108

6109+
if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
6110+
ext4_stop_mmpd(sbi);
6111+
61106112
/*
61116113
* Some options can be enabled by ext4 and/or by VFS mount flag
61126114
* either way we need to make sure it matches in both *flags and
@@ -6140,6 +6142,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
61406142
for (i = 0; i < EXT4_MAXQUOTAS; i++)
61416143
kfree(to_free[i]);
61426144
#endif
6145+
if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
6146+
ext4_stop_mmpd(sbi);
61436147
kfree(orig_data);
61446148
return err;
61456149
}

0 commit comments

Comments
 (0)