
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICLL1L -------------------------------- During out test, system will panic during prepare_binprm if the binary data is in tmpfs and is corrupt as follow: Internal error: synchronous external abort: ffffffff96000410 [#1] SMP CPU: 468 PID: 15075 Comm: bash Kdump: loaded Not tainted 5.10.0+ #8 Call trace: __memcpy+0x100/0x180 copy_page_to_iter+0x150/0x210 shmem_file_read_iter+0x1f8/0x464 __kernel_read+0x100/0x2bc kernel_read+0x60/0x90 search_binary_handler+0x5c/0x354 exec_binprm+0x5c/0x1dc bprm_execve.part.0+0xa0/0x130 bprm_execve+0x58/0xa0 do_execveat_common+0x1b0/0x230 __arm64_sys_execve+0x48/0x70 invoke_syscall+0x50/0x134 el0_svc_common.constprop.0+0x10c/0x124 do_el0_svc+0x34/0xe0 el0_svc+0x20/0x30 el0_sync_handler+0xb8/0xc0 fast_work_pending464+0x178/0x190 Code: d503201f d503201f d503201f d503201f (a8c12027) SMP: stopping secondary CPUs To fix this, add machine check safe support for bprm_execve if binrpm is read by shmem_file_read_iter. Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- fs/exec.c | 16 +++++++++++++++- mm/shmem.c | 10 +++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 371f96c3d5b8..17e11c9bfa30 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1685,10 +1685,24 @@ static int bprm_creds_from_file(struct linux_binprm *bprm) */ static int prepare_binprm(struct linux_binprm *bprm) { + unsigned int flags = 0; loff_t pos = 0; + int ret; + + /* + * Update task flag with PF_MCS to enable mcs support during + * reading binrpm + */ + if (IS_ENABLED(CONFIG_ARM64) && IS_ENABLED(CONFIG_ARCH_HAS_COPY_MC) && + !(current->flags & PF_MCS)) + flags = PF_MCS; + current->flags |= flags; memset(bprm->buf, 0, BINPRM_BUF_SIZE); - return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos); + ret = kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos); + current->flags &= ~flags; + + return ret; } /* diff --git a/mm/shmem.c b/mm/shmem.c index 9cb612d1153b..a5e7ed01943b 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2601,10 +2601,15 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to) int error = 0; ssize_t retval = 0; loff_t *ppos = &iocb->ki_pos; + bool use_copy_mc = false; index = *ppos >> PAGE_SHIFT; offset = *ppos & ~PAGE_MASK; + if (IS_ENABLED(CONFIG_ARM64) && IS_ENABLED(CONFIG_ARCH_HAS_COPY_MC) && + (current->flags & PF_MCS) && iov_iter_is_kvec(to)) + use_copy_mc = true; + for (;;) { struct page *page = NULL; pgoff_t end_index; @@ -2664,7 +2669,10 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to) * Ok, we have the page, and it's up-to-date, so * now we can copy it to user space... */ - ret = copy_page_to_iter(page, offset, nr, to); + if (use_copy_mc) + ret = copy_mc_page_to_kvec_iter(page, offset, nr, to); + else + ret = copy_page_to_iter(page, offset, nr, to); put_page(page); } else if (iter_is_iovec(to)) { -- 2.43.0