From: Sasha Levin Date: Wed, 9 Aug 2023 01:43:44 +0000 (-0400) Subject: Fixes for 6.1 X-Git-Tag: v4.14.322~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a6e6fc026907723963359256487e5e358f26c823;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/arm64-fpsimd-track-the-saved-fpsimd-state-type-separ.patch b/queue-6.1/arm64-fpsimd-track-the-saved-fpsimd-state-type-separ.patch new file mode 100644 index 00000000000..26506d09005 --- /dev/null +++ b/queue-6.1/arm64-fpsimd-track-the-saved-fpsimd-state-type-separ.patch @@ -0,0 +1,361 @@ +From 2867ca5ed28c178877ffdbb3987450491c8d61ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 09:46:34 +0000 +Subject: arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE + +From: Mark Brown + +[ Upstream commit baa8515281b30861cff3da7db70662d2a25c6440 ] + +When we save the state for the floating point registers this can be done +in the form visible through either the FPSIMD V registers or the SVE Z and +P registers. At present we track which format is currently used based on +TIF_SVE and the SME streaming mode state but particularly in the SVE case +this limits our options for optimising things, especially around syscalls. +Introduce a new enum which we place together with saved floating point +state in both thread_struct and the KVM guest state which explicitly +states which format is active and keep it up to date when we change it. + +At present we do not use this state except to verify that it has the +expected value when loading the state, future patches will introduce +functional changes. + +Signed-off-by: Mark Brown +Reviewed-by: Catalin Marinas +Reviewed-by: Marc Zyngier +Link: https://lore.kernel.org/r/20221115094640.112848-3-broonie@kernel.org +Signed-off-by: Will Deacon +Stable-dep-of: 045aecdfcb2e ("arm64/ptrace: Don't enable SVE when setting streaming SVE") +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/fpsimd.h | 2 +- + arch/arm64/include/asm/kvm_host.h | 12 ++++++- + arch/arm64/include/asm/processor.h | 6 ++++ + arch/arm64/kernel/fpsimd.c | 58 ++++++++++++++++++++++-------- + arch/arm64/kernel/process.c | 2 ++ + arch/arm64/kernel/ptrace.c | 3 ++ + arch/arm64/kernel/signal.c | 7 +++- + arch/arm64/kvm/fpsimd.c | 3 +- + 8 files changed, 74 insertions(+), 19 deletions(-) + +diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h +index c07e4abaca3d6..341705fcb7bb6 100644 +--- a/arch/arm64/include/asm/fpsimd.h ++++ b/arch/arm64/include/asm/fpsimd.h +@@ -61,7 +61,7 @@ extern void fpsimd_kvm_prepare(void); + extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state, + void *sve_state, unsigned int sve_vl, + void *za_state, unsigned int sme_vl, +- u64 *svcr); ++ u64 *svcr, enum fp_type *type); + + extern void fpsimd_flush_task_state(struct task_struct *target); + extern void fpsimd_save_and_flush_cpu_state(void); +diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h +index b5a8e8b3c691c..153e3dcc98c26 100644 +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -309,8 +309,18 @@ struct vcpu_reset_state { + struct kvm_vcpu_arch { + struct kvm_cpu_context ctxt; + +- /* Guest floating point state */ ++ /* ++ * Guest floating point state ++ * ++ * The architecture has two main floating point extensions, ++ * the original FPSIMD and SVE. These have overlapping ++ * register views, with the FPSIMD V registers occupying the ++ * low 128 bits of the SVE Z registers. When the core ++ * floating point code saves the register state of a task it ++ * records which view it saved in fp_type. ++ */ + void *sve_state; ++ enum fp_type fp_type; + unsigned int sve_max_vl; + u64 svcr; + +diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h +index 400f8956328b9..208434a2e9247 100644 +--- a/arch/arm64/include/asm/processor.h ++++ b/arch/arm64/include/asm/processor.h +@@ -122,6 +122,11 @@ enum vec_type { + ARM64_VEC_MAX, + }; + ++enum fp_type { ++ FP_STATE_FPSIMD, ++ FP_STATE_SVE, ++}; ++ + struct cpu_context { + unsigned long x19; + unsigned long x20; +@@ -152,6 +157,7 @@ struct thread_struct { + struct user_fpsimd_state fpsimd_state; + } uw; + ++ enum fp_type fp_type; /* registers FPSIMD or SVE? */ + unsigned int fpsimd_cpu; + void *sve_state; /* SVE registers, if any */ + void *za_state; /* ZA register, if any */ +diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c +index 63d796ad95411..af81a4a99b28e 100644 +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -125,6 +125,7 @@ struct fpsimd_last_state_struct { + u64 *svcr; + unsigned int sve_vl; + unsigned int sme_vl; ++ enum fp_type *fp_type; + }; + + static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state); +@@ -330,15 +331,6 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type, + * The task can execute SVE instructions while in userspace without + * trapping to the kernel. + * +- * When stored, Z0-Z31 (incorporating Vn in bits[127:0] or the +- * corresponding Zn), P0-P15 and FFR are encoded in +- * task->thread.sve_state, formatted appropriately for vector +- * length task->thread.sve_vl or, if SVCR.SM is set, +- * task->thread.sme_vl. +- * +- * task->thread.sve_state must point to a valid buffer at least +- * sve_state_size(task) bytes in size. +- * + * During any syscall, the kernel may optionally clear TIF_SVE and + * discard the vector state except for the FPSIMD subset. + * +@@ -348,7 +340,15 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type, + * do_sve_acc() to be called, which does some preparation and then + * sets TIF_SVE. + * +- * When stored, FPSIMD registers V0-V31 are encoded in ++ * During any syscall, the kernel may optionally clear TIF_SVE and ++ * discard the vector state except for the FPSIMD subset. ++ * ++ * The data will be stored in one of two formats: ++ * ++ * * FPSIMD only - FP_STATE_FPSIMD: ++ * ++ * When the FPSIMD only state stored task->thread.fp_type is set to ++ * FP_STATE_FPSIMD, the FPSIMD registers V0-V31 are encoded in + * task->thread.uw.fpsimd_state; bits [max : 128] for each of Z0-Z31 are + * logically zero but not stored anywhere; P0-P15 and FFR are not + * stored and have unspecified values from userspace's point of +@@ -358,6 +358,19 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type, + * task->thread.sve_state does not need to be non-NULL, valid or any + * particular size: it must not be dereferenced. + * ++ * * SVE state - FP_STATE_SVE: ++ * ++ * When the full SVE state is stored task->thread.fp_type is set to ++ * FP_STATE_SVE and Z0-Z31 (incorporating Vn in bits[127:0] or the ++ * corresponding Zn), P0-P15 and FFR are encoded in in ++ * task->thread.sve_state, formatted appropriately for vector ++ * length task->thread.sve_vl or, if SVCR.SM is set, ++ * task->thread.sme_vl. The storage for the vector registers in ++ * task->thread.uw.fpsimd_state should be ignored. ++ * ++ * task->thread.sve_state must point to a valid buffer at least ++ * sve_state_size(task) bytes in size. ++ * + * * FPSR and FPCR are always stored in task->thread.uw.fpsimd_state + * irrespective of whether TIF_SVE is clear or set, since these are + * not vector length dependent. +@@ -404,12 +417,15 @@ static void task_fpsimd_load(void) + } + } + +- if (restore_sve_regs) ++ if (restore_sve_regs) { ++ WARN_ON_ONCE(current->thread.fp_type != FP_STATE_SVE); + sve_load_state(sve_pffr(¤t->thread), + ¤t->thread.uw.fpsimd_state.fpsr, + restore_ffr); +- else ++ } else { ++ WARN_ON_ONCE(current->thread.fp_type != FP_STATE_FPSIMD); + fpsimd_load_state(¤t->thread.uw.fpsimd_state); ++ } + } + + /* +@@ -474,8 +490,10 @@ static void fpsimd_save(void) + sve_save_state((char *)last->sve_state + + sve_ffr_offset(vl), + &last->st->fpsr, save_ffr); ++ *last->fp_type = FP_STATE_SVE; + } else { + fpsimd_save_state(last->st); ++ *last->fp_type = FP_STATE_FPSIMD; + } + } + +@@ -851,8 +869,10 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type, + + fpsimd_flush_task_state(task); + if (test_and_clear_tsk_thread_flag(task, TIF_SVE) || +- thread_sm_enabled(&task->thread)) ++ thread_sm_enabled(&task->thread)) { + sve_to_fpsimd(task); ++ task->thread.fp_type = FP_STATE_FPSIMD; ++ } + + if (system_supports_sme()) { + if (type == ARM64_VEC_SME || +@@ -1386,6 +1406,7 @@ static void sve_init_regs(void) + fpsimd_bind_task_to_cpu(); + } else { + fpsimd_to_sve(current); ++ current->thread.fp_type = FP_STATE_SVE; + } + } + +@@ -1614,6 +1635,8 @@ void fpsimd_flush_thread(void) + current->thread.svcr = 0; + } + ++ current->thread.fp_type = FP_STATE_FPSIMD; ++ + put_cpu_fpsimd_context(); + kfree(sve_state); + kfree(za_state); +@@ -1662,8 +1685,10 @@ void fpsimd_kvm_prepare(void) + */ + get_cpu_fpsimd_context(); + +- if (test_and_clear_thread_flag(TIF_SVE)) ++ if (test_and_clear_thread_flag(TIF_SVE)) { + sve_to_fpsimd(current); ++ current->thread.fp_type = FP_STATE_FPSIMD; ++ } + + put_cpu_fpsimd_context(); + } +@@ -1685,6 +1710,7 @@ static void fpsimd_bind_task_to_cpu(void) + last->sve_vl = task_get_sve_vl(current); + last->sme_vl = task_get_sme_vl(current); + last->svcr = ¤t->thread.svcr; ++ last->fp_type = ¤t->thread.fp_type; + current->thread.fpsimd_cpu = smp_processor_id(); + + /* +@@ -1708,7 +1734,8 @@ static void fpsimd_bind_task_to_cpu(void) + + void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state, + unsigned int sve_vl, void *za_state, +- unsigned int sme_vl, u64 *svcr) ++ unsigned int sme_vl, u64 *svcr, ++ enum fp_type *type) + { + struct fpsimd_last_state_struct *last = + this_cpu_ptr(&fpsimd_last_state); +@@ -1722,6 +1749,7 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state, + last->za_state = za_state; + last->sve_vl = sve_vl; + last->sme_vl = sme_vl; ++ last->fp_type = type; + } + + /* +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index 044a7d7f1f6ad..19cd05eea3f0e 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -331,6 +331,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) + clear_tsk_thread_flag(dst, TIF_SME); + } + ++ dst->thread.fp_type = FP_STATE_FPSIMD; ++ + /* clear any pending asynchronous tag fault raised by the parent */ + clear_tsk_thread_flag(dst, TIF_MTE_ASYNC_FAULT); + +diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c +index 92bc9a2d702cb..30e71a0b3955c 100644 +--- a/arch/arm64/kernel/ptrace.c ++++ b/arch/arm64/kernel/ptrace.c +@@ -909,6 +909,7 @@ static int sve_set_common(struct task_struct *target, + clear_tsk_thread_flag(target, TIF_SVE); + if (type == ARM64_VEC_SME) + fpsimd_force_sync_to_sve(target); ++ target->thread.fp_type = FP_STATE_FPSIMD; + goto out; + } + +@@ -931,6 +932,7 @@ static int sve_set_common(struct task_struct *target, + if (!target->thread.sve_state) { + ret = -ENOMEM; + clear_tsk_thread_flag(target, TIF_SVE); ++ target->thread.fp_type = FP_STATE_FPSIMD; + goto out; + } + +@@ -942,6 +944,7 @@ static int sve_set_common(struct task_struct *target, + */ + fpsimd_sync_to_sve(target); + set_tsk_thread_flag(target, TIF_SVE); ++ target->thread.fp_type = FP_STATE_SVE; + + BUILD_BUG_ON(SVE_PT_SVE_OFFSET != sizeof(header)); + start = SVE_PT_SVE_OFFSET; +diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c +index 43adbfa5ead78..be279fd482480 100644 +--- a/arch/arm64/kernel/signal.c ++++ b/arch/arm64/kernel/signal.c +@@ -207,6 +207,7 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx) + __get_user_error(fpsimd.fpcr, &ctx->fpcr, err); + + clear_thread_flag(TIF_SVE); ++ current->thread.fp_type = FP_STATE_FPSIMD; + + /* load the hardware registers from the fpsimd_state structure */ + if (!err) +@@ -297,6 +298,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user) + if (sve.head.size <= sizeof(*user->sve)) { + clear_thread_flag(TIF_SVE); + current->thread.svcr &= ~SVCR_SM_MASK; ++ current->thread.fp_type = FP_STATE_FPSIMD; + goto fpsimd_only; + } + +@@ -332,6 +334,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user) + current->thread.svcr |= SVCR_SM_MASK; + else + set_thread_flag(TIF_SVE); ++ current->thread.fp_type = FP_STATE_SVE; + + fpsimd_only: + /* copy the FP and status/control registers */ +@@ -937,9 +940,11 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, + * FPSIMD register state - flush the saved FPSIMD + * register state in case it gets loaded. + */ +- if (current->thread.svcr & SVCR_SM_MASK) ++ if (current->thread.svcr & SVCR_SM_MASK) { + memset(¤t->thread.uw.fpsimd_state, 0, + sizeof(current->thread.uw.fpsimd_state)); ++ current->thread.fp_type = FP_STATE_FPSIMD; ++ } + + current->thread.svcr &= ~(SVCR_ZA_MASK | + SVCR_SM_MASK); +diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c +index 51ca78b31b952..a4b4502ad850a 100644 +--- a/arch/arm64/kvm/fpsimd.c ++++ b/arch/arm64/kvm/fpsimd.c +@@ -140,7 +140,8 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) + fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.fp_regs, + vcpu->arch.sve_state, + vcpu->arch.sve_max_vl, +- NULL, 0, &vcpu->arch.svcr); ++ NULL, 0, &vcpu->arch.svcr, ++ &vcpu->arch.fp_type); + + clear_thread_flag(TIF_FOREIGN_FPSTATE); + update_thread_flag(TIF_SVE, vcpu_has_sve(vcpu)); +-- +2.40.1 + diff --git a/queue-6.1/arm64-ptrace-don-t-enable-sve-when-setting-streaming.patch b/queue-6.1/arm64-ptrace-don-t-enable-sve-when-setting-streaming.patch new file mode 100644 index 00000000000..13d6014d407 --- /dev/null +++ b/queue-6.1/arm64-ptrace-don-t-enable-sve-when-setting-streaming.patch @@ -0,0 +1,62 @@ +From 0bd1d67586c6015e6ea2b6e99230c195514a7a8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Aug 2023 19:33:21 +0100 +Subject: arm64/ptrace: Don't enable SVE when setting streaming SVE + +From: Mark Brown + +[ Upstream commit 045aecdfcb2e060db142d83a0f4082380c465d2c ] + +Systems which implement SME without also implementing SVE are +architecturally valid but were not initially supported by the kernel, +unfortunately we missed one issue in the ptrace code. + +The SVE register setting code is shared between SVE and streaming mode +SVE. When we set full SVE register state we currently enable TIF_SVE +unconditionally, in the case where streaming SVE is being configured on a +system that supports vanilla SVE this is not an issue since we always +initialise enough state for both vector lengths but on a system which only +support SME it will result in us attempting to restore the SVE vector +length after having set streaming SVE registers. + +Fix this by making the enabling of SVE conditional on setting SVE vector +state. If we set streaming SVE state and SVE was not already enabled this +will result in a SVE access trap on next use of normal SVE, this will cause +us to flush our register state but this is fine since the only way to +trigger a SVE access trap would be to exit streaming mode which will cause +the in register state to be flushed anyway. + +Fixes: e12310a0d30f ("arm64/sme: Implement ptrace support for streaming mode SVE registers") +Signed-off-by: Mark Brown +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20230803-arm64-fix-ptrace-ssve-no-sve-v1-1-49df214bfb3e@kernel.org +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/kernel/ptrace.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c +index 30e71a0b3955c..5da65d235ce26 100644 +--- a/arch/arm64/kernel/ptrace.c ++++ b/arch/arm64/kernel/ptrace.c +@@ -939,11 +939,13 @@ static int sve_set_common(struct task_struct *target, + /* + * Ensure target->thread.sve_state is up to date with target's + * FPSIMD regs, so that a short copyin leaves trailing +- * registers unmodified. Always enable SVE even if going into +- * streaming mode. ++ * registers unmodified. Only enable SVE if we are ++ * configuring normal SVE, a system with streaming SVE may not ++ * have normal SVE. + */ + fpsimd_sync_to_sve(target); +- set_tsk_thread_flag(target, TIF_SVE); ++ if (type == ARM64_VEC_SVE) ++ set_tsk_thread_flag(target, TIF_SVE); + target->thread.fp_type = FP_STATE_SVE; + + BUILD_BUG_ON(SVE_PT_SVE_OFFSET != sizeof(header)); +-- +2.40.1 + diff --git a/queue-6.1/exfat-check-if-filename-entries-exceeds-max-filename.patch b/queue-6.1/exfat-check-if-filename-entries-exceeds-max-filename.patch new file mode 100644 index 00000000000..45b7cc5cde3 --- /dev/null +++ b/queue-6.1/exfat-check-if-filename-entries-exceeds-max-filename.patch @@ -0,0 +1,65 @@ +From 4abe51e50955e8741a7b7537879b829fdcfb5675 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Jul 2023 21:59:37 +0900 +Subject: exfat: check if filename entries exceeds max filename length + +From: Namjae Jeon + +[ Upstream commit d42334578eba1390859012ebb91e1e556d51db49 ] + +exfat_extract_uni_name copies characters from a given file name entry into +the 'uniname' variable. This variable is actually defined on the stack of +the exfat_readdir() function. According to the definition of +the 'exfat_uni_name' type, the file name should be limited 255 characters +(+ null teminator space), but the exfat_get_uniname_from_ext_entry() +function can write more characters because there is no check if filename +entries exceeds max filename length. This patch add the check not to copy +filename characters when exceeding max filename length. + +Cc: stable@vger.kernel.org +Cc: Yuezhang Mo +Reported-by: Maxim Suhanov +Reviewed-by: Sungjong Seo +Signed-off-by: Namjae Jeon +Signed-off-by: Sasha Levin +--- + fs/exfat/dir.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c +index 78de6f67f882d..51b03b0dd5f75 100644 +--- a/fs/exfat/dir.c ++++ b/fs/exfat/dir.c +@@ -34,6 +34,7 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb, + { + int i; + struct exfat_entry_set_cache *es; ++ unsigned int uni_len = 0, len; + + es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES); + if (!es) +@@ -52,7 +53,10 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb, + if (exfat_get_entry_type(ep) != TYPE_EXTEND) + break; + +- exfat_extract_uni_name(ep, uniname); ++ len = exfat_extract_uni_name(ep, uniname); ++ uni_len += len; ++ if (len != EXFAT_FILE_NAME_LEN || uni_len >= MAX_NAME_LENGTH) ++ break; + uniname += EXFAT_FILE_NAME_LEN; + } + +@@ -1024,7 +1028,8 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, + if (entry_type == TYPE_EXTEND) { + unsigned short entry_uniname[16], unichar; + +- if (step != DIRENT_STEP_NAME) { ++ if (step != DIRENT_STEP_NAME || ++ name_len >= MAX_NAME_LENGTH) { + step = DIRENT_STEP_FILE; + continue; + } +-- +2.40.1 + diff --git a/queue-6.1/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch b/queue-6.1/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch new file mode 100644 index 00000000000..89bef2dbd01 --- /dev/null +++ b/queue-6.1/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch @@ -0,0 +1,141 @@ +From c9f01375defd9a57468adc115167488647778898 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 May 2023 11:58:22 +0800 +Subject: f2fs: don't reset unchangable mount option in f2fs_remount() + +From: Chao Yu + +[ Upstream commit 458c15dfbce62c35fefd9ca637b20a051309c9f1 ] + +syzbot reports a bug as below: + +general protection fault, probably for non-canonical address 0xdffffc0000000009: 0000 [#1] PREEMPT SMP KASAN +RIP: 0010:__lock_acquire+0x69/0x2000 kernel/locking/lockdep.c:4942 +Call Trace: + lock_acquire+0x1e3/0x520 kernel/locking/lockdep.c:5691 + __raw_write_lock include/linux/rwlock_api_smp.h:209 [inline] + _raw_write_lock+0x2e/0x40 kernel/locking/spinlock.c:300 + __drop_extent_tree+0x3ac/0x660 fs/f2fs/extent_cache.c:1100 + f2fs_drop_extent_tree+0x17/0x30 fs/f2fs/extent_cache.c:1116 + f2fs_insert_range+0x2d5/0x3c0 fs/f2fs/file.c:1664 + f2fs_fallocate+0x4e4/0x6d0 fs/f2fs/file.c:1838 + vfs_fallocate+0x54b/0x6b0 fs/open.c:324 + ksys_fallocate fs/open.c:347 [inline] + __do_sys_fallocate fs/open.c:355 [inline] + __se_sys_fallocate fs/open.c:353 [inline] + __x64_sys_fallocate+0xbd/0x100 fs/open.c:353 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +The root cause is race condition as below: +- since it tries to remount rw filesystem, so that do_remount won't +call sb_prepare_remount_readonly to block fallocate, there may be race +condition in between remount and fallocate. +- in f2fs_remount(), default_options() will reset mount option to default +one, and then update it based on result of parse_options(), so there is +a hole which race condition can happen. + +Thread A Thread B +- f2fs_fill_super + - parse_options + - clear_opt(READ_EXTENT_CACHE) + +- f2fs_remount + - default_options + - set_opt(READ_EXTENT_CACHE) + - f2fs_fallocate + - f2fs_insert_range + - f2fs_drop_extent_tree + - __drop_extent_tree + - __may_extent_tree + - test_opt(READ_EXTENT_CACHE) return true + - write_lock(&et->lock) access NULL pointer + - parse_options + - clear_opt(READ_EXTENT_CACHE) + +Cc: +Reported-by: syzbot+d015b6c2fbb5c383bf08@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-f2fs-devel/20230522124203.3838360-1-chao@kernel.org +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 36bb1c969e8bb..ff47aad636e5b 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -2040,9 +2040,22 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) + return 0; + } + +-static void default_options(struct f2fs_sb_info *sbi) ++static void default_options(struct f2fs_sb_info *sbi, bool remount) + { + /* init some FS parameters */ ++ if (!remount) { ++ set_opt(sbi, READ_EXTENT_CACHE); ++ clear_opt(sbi, DISABLE_CHECKPOINT); ++ ++ if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) ++ set_opt(sbi, DISCARD); ++ ++ if (f2fs_sb_has_blkzoned(sbi)) ++ F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_SECTION; ++ else ++ F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_BLOCK; ++ } ++ + if (f2fs_sb_has_readonly(sbi)) + F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE; + else +@@ -2065,23 +2078,16 @@ static void default_options(struct f2fs_sb_info *sbi) + set_opt(sbi, INLINE_XATTR); + set_opt(sbi, INLINE_DATA); + set_opt(sbi, INLINE_DENTRY); +- set_opt(sbi, READ_EXTENT_CACHE); + set_opt(sbi, NOHEAP); +- clear_opt(sbi, DISABLE_CHECKPOINT); + set_opt(sbi, MERGE_CHECKPOINT); + F2FS_OPTION(sbi).unusable_cap = 0; + sbi->sb->s_flags |= SB_LAZYTIME; + if (!f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) + set_opt(sbi, FLUSH_MERGE); +- if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) +- set_opt(sbi, DISCARD); +- if (f2fs_sb_has_blkzoned(sbi)) { ++ if (f2fs_sb_has_blkzoned(sbi)) + F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; +- F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_SECTION; +- } else { ++ else + F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; +- F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_BLOCK; +- } + + #ifdef CONFIG_F2FS_FS_XATTR + set_opt(sbi, XATTR_USER); +@@ -2253,7 +2259,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) + clear_sbi_flag(sbi, SBI_NEED_SB_WRITE); + } + +- default_options(sbi); ++ default_options(sbi, true); + + /* parse mount options */ + err = parse_options(sb, data, true); +@@ -4150,7 +4156,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) + sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid, + sizeof(raw_super->uuid)); + +- default_options(sbi); ++ default_options(sbi, false); + /* parse mount options */ + options = kstrdup((const char *)data, GFP_KERNEL); + if (data && !options) { +-- +2.40.1 + diff --git a/queue-6.1/f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch b/queue-6.1/f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch new file mode 100644 index 00000000000..78d1ed61968 --- /dev/null +++ b/queue-6.1/f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch @@ -0,0 +1,66 @@ +From 44f4015850f033cb7cec5a169d3c7cc5d0c2d20b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 17:15:01 +0800 +Subject: f2fs: fix to set flush_merge opt and show noflush_merge + +From: Yangtao Li + +[ Upstream commit 967eaad1fed5f6335ea97a47d45214744dc57925 ] + +Some minor modifications to flush_merge and related parameters: + + 1.The FLUSH_MERGE opt is set by default only in non-ro mode. + 2.When ro and merge are set at the same time, an error is reported. + 3.Display noflush_merge mount opt. + +Suggested-by: Chao Yu +Signed-off-by: Yangtao Li +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 458c15dfbce6 ("f2fs: don't reset unchangable mount option in f2fs_remount()") +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index b6dad389fa144..36bb1c969e8bb 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -1347,6 +1347,12 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) + return -EINVAL; + } + ++ if ((f2fs_sb_has_readonly(sbi) || f2fs_readonly(sbi->sb)) && ++ test_opt(sbi, FLUSH_MERGE)) { ++ f2fs_err(sbi, "FLUSH_MERGE not compatible with readonly mode"); ++ return -EINVAL; ++ } ++ + if (f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) { + f2fs_err(sbi, "Allow to mount readonly mode only"); + return -EROFS; +@@ -1933,8 +1939,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) + seq_puts(seq, ",inline_dentry"); + else + seq_puts(seq, ",noinline_dentry"); +- if (!f2fs_readonly(sbi->sb) && test_opt(sbi, FLUSH_MERGE)) ++ if (test_opt(sbi, FLUSH_MERGE)) + seq_puts(seq, ",flush_merge"); ++ else ++ seq_puts(seq, ",noflush_merge"); + if (test_opt(sbi, NOBARRIER)) + seq_puts(seq, ",nobarrier"); + if (test_opt(sbi, FASTBOOT)) +@@ -2063,7 +2071,8 @@ static void default_options(struct f2fs_sb_info *sbi) + set_opt(sbi, MERGE_CHECKPOINT); + F2FS_OPTION(sbi).unusable_cap = 0; + sbi->sb->s_flags |= SB_LAZYTIME; +- set_opt(sbi, FLUSH_MERGE); ++ if (!f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) ++ set_opt(sbi, FLUSH_MERGE); + if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) + set_opt(sbi, DISCARD); + if (f2fs_sb_has_blkzoned(sbi)) { +-- +2.40.1 + diff --git a/queue-6.1/kvm-arm64-discard-any-sve-state-when-entering-kvm-gu.patch b/queue-6.1/kvm-arm64-discard-any-sve-state-when-entering-kvm-gu.patch new file mode 100644 index 00000000000..d6630f03ce8 --- /dev/null +++ b/queue-6.1/kvm-arm64-discard-any-sve-state-when-entering-kvm-gu.patch @@ -0,0 +1,99 @@ +From d2617b724dd53b03ad06bce44b7d4d098244f403 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 09:46:33 +0000 +Subject: KVM: arm64: Discard any SVE state when entering KVM guests + +From: Mark Brown + +[ Upstream commit 93ae6b01bafee8fa385aa25ee7ebdb40057f6abe ] + +Since 8383741ab2e773a99 (KVM: arm64: Get rid of host SVE tracking/saving) +KVM has not tracked the host SVE state, relying on the fact that we +currently disable SVE whenever we perform a syscall. This may not be true +in future since performance optimisation may result in us keeping SVE +enabled in order to avoid needing to take access traps to reenable it. +Handle this by clearing TIF_SVE and converting the stored task state to +FPSIMD format when preparing to run the guest. This is done with a new +call fpsimd_kvm_prepare() to keep the direct state manipulation +functions internal to fpsimd.c. + +Signed-off-by: Mark Brown +Reviewed-by: Catalin Marinas +Reviewed-by: Marc Zyngier +Link: https://lore.kernel.org/r/20221115094640.112848-2-broonie@kernel.org +Signed-off-by: Will Deacon +Stable-dep-of: 045aecdfcb2e ("arm64/ptrace: Don't enable SVE when setting streaming SVE") +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/fpsimd.h | 1 + + arch/arm64/kernel/fpsimd.c | 23 +++++++++++++++++++++++ + arch/arm64/kvm/fpsimd.c | 3 ++- + 3 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h +index 6f86b7ab6c28f..c07e4abaca3d6 100644 +--- a/arch/arm64/include/asm/fpsimd.h ++++ b/arch/arm64/include/asm/fpsimd.h +@@ -56,6 +56,7 @@ extern void fpsimd_signal_preserve_current_state(void); + extern void fpsimd_preserve_current_state(void); + extern void fpsimd_restore_current_state(void); + extern void fpsimd_update_current_state(struct user_fpsimd_state const *state); ++extern void fpsimd_kvm_prepare(void); + + extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state, + void *sve_state, unsigned int sve_vl, +diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c +index 356036babd093..63d796ad95411 100644 +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -1645,6 +1645,29 @@ void fpsimd_signal_preserve_current_state(void) + sve_to_fpsimd(current); + } + ++/* ++ * Called by KVM when entering the guest. ++ */ ++void fpsimd_kvm_prepare(void) ++{ ++ if (!system_supports_sve()) ++ return; ++ ++ /* ++ * KVM does not save host SVE state since we can only enter ++ * the guest from a syscall so the ABI means that only the ++ * non-saved SVE state needs to be saved. If we have left ++ * SVE enabled for performance reasons then update the task ++ * state to be FPSIMD only. ++ */ ++ get_cpu_fpsimd_context(); ++ ++ if (test_and_clear_thread_flag(TIF_SVE)) ++ sve_to_fpsimd(current); ++ ++ put_cpu_fpsimd_context(); ++} ++ + /* + * Associate current's FPSIMD context with this cpu + * The caller must have ownership of the cpu FPSIMD context before calling +diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c +index ec8e4494873d4..51ca78b31b952 100644 +--- a/arch/arm64/kvm/fpsimd.c ++++ b/arch/arm64/kvm/fpsimd.c +@@ -75,11 +75,12 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu) + void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) + { + BUG_ON(!current->mm); +- BUG_ON(test_thread_flag(TIF_SVE)); + + if (!system_supports_fpsimd()) + return; + ++ fpsimd_kvm_prepare(); ++ + vcpu->arch.fp_state = FP_STATE_HOST_OWNED; + + vcpu_clear_flag(vcpu, HOST_SVE_ENABLED); +-- +2.40.1 + diff --git a/queue-6.1/selftests-rseq-play-nice-with-binaries-statically-li.patch b/queue-6.1/selftests-rseq-play-nice-with-binaries-statically-li.patch new file mode 100644 index 00000000000..2632b3413b8 --- /dev/null +++ b/queue-6.1/selftests-rseq-play-nice-with-binaries-statically-li.patch @@ -0,0 +1,84 @@ +From 61e64ca17f1f4f39218216091404cb04a843b3df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Jul 2023 15:33:52 -0700 +Subject: selftests/rseq: Play nice with binaries statically linked against + glibc 2.35+ + +From: Sean Christopherson + +[ Upstream commit 3bcbc20942db5d738221cca31a928efc09827069 ] + +To allow running rseq and KVM's rseq selftests as statically linked +binaries, initialize the various "trampoline" pointers to point directly +at the expect glibc symbols, and skip the dlysm() lookups if the rseq +size is non-zero, i.e. the binary is statically linked *and* the libc +registered its own rseq. + +Define weak versions of the symbols so as not to break linking against +libc versions that don't support rseq in any capacity. + +The KVM selftests in particular are often statically linked so that they +can be run on targets with very limited runtime environments, i.e. test +machines. + +Fixes: 233e667e1ae3 ("selftests/rseq: Uplift rseq selftests for compatibility with glibc-2.35") +Cc: Aaron Lewis +Cc: kvm@vger.kernel.org +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Message-Id: <20230721223352.2333911-1-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/rseq/rseq.c | 28 ++++++++++++++++++++++------ + 1 file changed, 22 insertions(+), 6 deletions(-) + +diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c +index 4177f9507bbee..b736a5169aad0 100644 +--- a/tools/testing/selftests/rseq/rseq.c ++++ b/tools/testing/selftests/rseq/rseq.c +@@ -32,9 +32,17 @@ + #include "../kselftest.h" + #include "rseq.h" + +-static const ptrdiff_t *libc_rseq_offset_p; +-static const unsigned int *libc_rseq_size_p; +-static const unsigned int *libc_rseq_flags_p; ++/* ++ * Define weak versions to play nice with binaries that are statically linked ++ * against a libc that doesn't support registering its own rseq. ++ */ ++__weak ptrdiff_t __rseq_offset; ++__weak unsigned int __rseq_size; ++__weak unsigned int __rseq_flags; ++ ++static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset; ++static const unsigned int *libc_rseq_size_p = &__rseq_size; ++static const unsigned int *libc_rseq_flags_p = &__rseq_flags; + + /* Offset from the thread pointer to the rseq area. */ + ptrdiff_t rseq_offset; +@@ -108,9 +116,17 @@ int rseq_unregister_current_thread(void) + static __attribute__((constructor)) + void rseq_init(void) + { +- libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset"); +- libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size"); +- libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags"); ++ /* ++ * If the libc's registered rseq size isn't already valid, it may be ++ * because the binary is dynamically linked and not necessarily due to ++ * libc not having registered a restartable sequence. Try to find the ++ * symbols if that's the case. ++ */ ++ if (!*libc_rseq_size_p) { ++ libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset"); ++ libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size"); ++ libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags"); ++ } + if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p && + *libc_rseq_size_p != 0) { + /* rseq registration owned by glibc */ +-- +2.40.1 + diff --git a/queue-6.1/series b/queue-6.1/series index 5294e339d5e..1847fc472c6 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -114,3 +114,10 @@ mtd-rawnand-rockchip-align-hwecc-vs.-raw-page-helper.patch mtd-rawnand-fsl_upm-fix-an-off-by-one-test-in-fun_ex.patch powerpc-mm-altmap-fix-altmap-boundary-check.patch drm-imx-ipuv3-fix-front-porch-adjustment-upon-hactiv.patch +selftests-rseq-play-nice-with-binaries-statically-li.patch +f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch +f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch +exfat-check-if-filename-entries-exceeds-max-filename.patch +kvm-arm64-discard-any-sve-state-when-entering-kvm-gu.patch +arm64-fpsimd-track-the-saved-fpsimd-state-type-separ.patch +arm64-ptrace-don-t-enable-sve-when-setting-streaming.patch