From: Greg Kroah-Hartman Date: Sun, 26 Aug 2018 06:17:38 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v3.18.120~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=586e5caaf64530c41812704ad2d2dbc39b3b144e;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: ovl-do-d_type-check-only-if-work-dir-creation-was-successful.patch ovl-ensure-upper-filesystem-supports-d_type.patch ovl-warn-instead-of-error-if-d_type-is-not-supported.patch x86-mm-fix-use-after-free-of-ldt_struct.patch --- diff --git a/queue-4.4/ovl-do-d_type-check-only-if-work-dir-creation-was-successful.patch b/queue-4.4/ovl-do-d_type-check-only-if-work-dir-creation-was-successful.patch new file mode 100644 index 00000000000..62cfa1f6e31 --- /dev/null +++ b/queue-4.4/ovl-do-d_type-check-only-if-work-dir-creation-was-successful.patch @@ -0,0 +1,55 @@ +From 21765194cecf2e4514ad75244df459f188140a0f Mon Sep 17 00:00:00 2001 +From: Vivek Goyal +Date: Fri, 20 May 2016 09:04:26 -0400 +Subject: ovl: Do d_type check only if work dir creation was successful + +From: Vivek Goyal + +commit 21765194cecf2e4514ad75244df459f188140a0f upstream. + +d_type check requires successful creation of workdir as iterates +through work dir and expects work dir to be present in it. If that's +not the case, this check will always return d_type not supported even +if underlying filesystem might be supporting it. + +So don't do this check if work dir creation failed in previous step. + +Signed-off-by: Vivek Goyal +Signed-off-by: Miklos Szeredi +Signed-off-by: SZ Lin (林上智) +Signed-off-by: Greg Kroah-Hartman + +--- + fs/overlayfs/super.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -1058,16 +1058,19 @@ static int ovl_fill_super(struct super_b + /* + * Upper should support d_type, else whiteouts are visible. + * Given workdir and upper are on same fs, we can do +- * iterate_dir() on workdir. ++ * iterate_dir() on workdir. This check requires successful ++ * creation of workdir in previous step. + */ +- err = ovl_check_d_type_supported(&workpath); +- if (err < 0) +- goto out_put_workdir; ++ if (ufs->workdir) { ++ err = ovl_check_d_type_supported(&workpath); ++ if (err < 0) ++ goto out_put_workdir; + +- if (!err) { +- pr_err("overlayfs: upper fs needs to support d_type.\n"); +- err = -EINVAL; +- goto out_put_workdir; ++ if (!err) { ++ pr_err("overlayfs: upper fs needs to support d_type.\n"); ++ err = -EINVAL; ++ goto out_put_workdir; ++ } + } + } + diff --git a/queue-4.4/ovl-ensure-upper-filesystem-supports-d_type.patch b/queue-4.4/ovl-ensure-upper-filesystem-supports-d_type.patch new file mode 100644 index 00000000000..ea5c039bf35 --- /dev/null +++ b/queue-4.4/ovl-ensure-upper-filesystem-supports-d_type.patch @@ -0,0 +1,116 @@ +From 45aebeaf4f67468f76bedf62923a576a519a9b68 Mon Sep 17 00:00:00 2001 +From: Vivek Goyal +Date: Mon, 22 Feb 2016 09:28:34 -0500 +Subject: ovl: Ensure upper filesystem supports d_type + +From: Vivek Goyal + +commit 45aebeaf4f67468f76bedf62923a576a519a9b68 upstream. + +In some instances xfs has been created with ftype=0 and there if a file +on lower fs is removed, overlay leaves a whiteout in upper fs but that +whiteout does not get filtered out and is visible to overlayfs users. + +And reason it does not get filtered out because upper filesystem does +not report file type of whiteout as DT_CHR during iterate_dir(). + +So it seems to be a requirement that upper filesystem support d_type for +overlayfs to work properly. Do this check during mount and fail if d_type +is not supported. + +Suggested-by: Dave Chinner +Signed-off-by: Vivek Goyal +Signed-off-by: Miklos Szeredi +Signed-off-by: SZ Lin (林上智) +Signed-off-by: Greg Kroah-Hartman + +--- + fs/overlayfs/overlayfs.h | 1 + + fs/overlayfs/readdir.c | 37 +++++++++++++++++++++++++++++++++++++ + fs/overlayfs/super.c | 15 +++++++++++++++ + 3 files changed, 53 insertions(+) + +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -163,6 +163,7 @@ extern const struct file_operations ovl_ + int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list); + void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list); + void ovl_cache_free(struct list_head *list); ++int ovl_check_d_type_supported(struct path *realpath); + + /* inode.c */ + int ovl_setattr(struct dentry *dentry, struct iattr *attr); +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -43,6 +43,7 @@ struct ovl_readdir_data { + struct ovl_cache_entry *first_maybe_whiteout; + int count; + int err; ++ bool d_type_supported; + }; + + struct ovl_dir_file { +@@ -581,3 +582,39 @@ void ovl_cleanup_whiteouts(struct dentry + } + mutex_unlock(&upper->d_inode->i_mutex); + } ++ ++static int ovl_check_d_type(struct dir_context *ctx, const char *name, ++ int namelen, loff_t offset, u64 ino, ++ unsigned int d_type) ++{ ++ struct ovl_readdir_data *rdd = ++ container_of(ctx, struct ovl_readdir_data, ctx); ++ ++ /* Even if d_type is not supported, DT_DIR is returned for . and .. */ ++ if (!strncmp(name, ".", namelen) || !strncmp(name, "..", namelen)) ++ return 0; ++ ++ if (d_type != DT_UNKNOWN) ++ rdd->d_type_supported = true; ++ ++ return 0; ++} ++ ++/* ++ * Returns 1 if d_type is supported, 0 not supported/unknown. Negative values ++ * if error is encountered. ++ */ ++int ovl_check_d_type_supported(struct path *realpath) ++{ ++ int err; ++ struct ovl_readdir_data rdd = { ++ .ctx.actor = ovl_check_d_type, ++ .d_type_supported = false, ++ }; ++ ++ err = ovl_dir_read(realpath, &rdd); ++ if (err) ++ return err; ++ ++ return rdd.d_type_supported; ++} +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -1054,6 +1054,21 @@ static int ovl_fill_super(struct super_b + sb->s_flags |= MS_RDONLY; + ufs->workdir = NULL; + } ++ ++ /* ++ * Upper should support d_type, else whiteouts are visible. ++ * Given workdir and upper are on same fs, we can do ++ * iterate_dir() on workdir. ++ */ ++ err = ovl_check_d_type_supported(&workpath); ++ if (err < 0) ++ goto out_put_workdir; ++ ++ if (!err) { ++ pr_err("overlayfs: upper fs needs to support d_type.\n"); ++ err = -EINVAL; ++ goto out_put_workdir; ++ } + } + + err = -ENOMEM; diff --git a/queue-4.4/ovl-warn-instead-of-error-if-d_type-is-not-supported.patch b/queue-4.4/ovl-warn-instead-of-error-if-d_type-is-not-supported.patch new file mode 100644 index 00000000000..2139c63b73b --- /dev/null +++ b/queue-4.4/ovl-warn-instead-of-error-if-d_type-is-not-supported.patch @@ -0,0 +1,56 @@ +From e7c0b5991dd1be7b6f6dc2b54a15a0f47b64b007 Mon Sep 17 00:00:00 2001 +From: Vivek Goyal +Date: Fri, 1 Jul 2016 10:02:44 -0400 +Subject: ovl: warn instead of error if d_type is not supported + +From: Vivek Goyal + +commit e7c0b5991dd1be7b6f6dc2b54a15a0f47b64b007 upstream. + +overlay needs underlying fs to support d_type. Recently I put in a +patch in to detect this condition and started failing mount if +underlying fs did not support d_type. + +But this breaks existing configurations over kernel upgrade. Those who +are running docker (partially broken configuration) with xfs not +supporting d_type, are surprised that after kernel upgrade docker does +not run anymore. + +https://github.com/docker/docker/issues/22937#issuecomment-229881315 + +So instead of erroring out, detect broken configuration and warn +about it. This should allow existing docker setups to continue +working after kernel upgrade. + +Signed-off-by: Vivek Goyal +Signed-off-by: Miklos Szeredi +Fixes: 45aebeaf4f67 ("ovl: Ensure upper filesystem supports d_type") +Cc: 4.6 +Signed-off-by: SZ Lin (林上智) +Signed-off-by: Greg Kroah-Hartman + +--- + fs/overlayfs/super.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -1066,11 +1066,13 @@ static int ovl_fill_super(struct super_b + if (err < 0) + goto out_put_workdir; + +- if (!err) { +- pr_err("overlayfs: upper fs needs to support d_type.\n"); +- err = -EINVAL; +- goto out_put_workdir; +- } ++ /* ++ * We allowed this configuration and don't want to ++ * break users over kernel upgrade. So warn instead ++ * of erroring out. ++ */ ++ if (!err) ++ pr_warn("overlayfs: upper fs needs to support d_type.\n"); + } + } + diff --git a/queue-4.4/series b/queue-4.4/series index 9f0b713081f..0d93f562464 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -1 +1,5 @@ x86-mm-pat-fix-l1tf-stable-backport-for-cpa.patch +x86-mm-fix-use-after-free-of-ldt_struct.patch +ovl-ensure-upper-filesystem-supports-d_type.patch +ovl-do-d_type-check-only-if-work-dir-creation-was-successful.patch +ovl-warn-instead-of-error-if-d_type-is-not-supported.patch diff --git a/queue-4.4/x86-mm-fix-use-after-free-of-ldt_struct.patch b/queue-4.4/x86-mm-fix-use-after-free-of-ldt_struct.patch new file mode 100644 index 00000000000..3c5d48c5a6f --- /dev/null +++ b/queue-4.4/x86-mm-fix-use-after-free-of-ldt_struct.patch @@ -0,0 +1,174 @@ +From ccd5b3235180eef3cfec337df1c8554ab151b5cc Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Thu, 24 Aug 2017 10:50:29 -0700 +Subject: x86/mm: Fix use-after-free of ldt_struct + +From: Eric Biggers + +commit ccd5b3235180eef3cfec337df1c8554ab151b5cc upstream. + +The following commit: + + 39a0526fb3f7 ("x86/mm: Factor out LDT init from context init") + +renamed init_new_context() to init_new_context_ldt() and added a new +init_new_context() which calls init_new_context_ldt(). However, the +error code of init_new_context_ldt() was ignored. Consequently, if a +memory allocation in alloc_ldt_struct() failed during a fork(), the +->context.ldt of the new task remained the same as that of the old task +(due to the memcpy() in dup_mm()). ldt_struct's are not intended to be +shared, so a use-after-free occurred after one task exited. + +Fix the bug by making init_new_context() pass through the error code of +init_new_context_ldt(). + +This bug was found by syzkaller, which encountered the following splat: + + BUG: KASAN: use-after-free in free_ldt_struct.part.2+0x10a/0x150 arch/x86/kernel/ldt.c:116 + Read of size 4 at addr ffff88006d2cb7c8 by task kworker/u9:0/3710 + + CPU: 1 PID: 3710 Comm: kworker/u9:0 Not tainted 4.13.0-rc4-next-20170811 #2 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + Call Trace: + __dump_stack lib/dump_stack.c:16 [inline] + dump_stack+0x194/0x257 lib/dump_stack.c:52 + print_address_description+0x73/0x250 mm/kasan/report.c:252 + kasan_report_error mm/kasan/report.c:351 [inline] + kasan_report+0x24e/0x340 mm/kasan/report.c:409 + __asan_report_load4_noabort+0x14/0x20 mm/kasan/report.c:429 + free_ldt_struct.part.2+0x10a/0x150 arch/x86/kernel/ldt.c:116 + free_ldt_struct arch/x86/kernel/ldt.c:173 [inline] + destroy_context_ldt+0x60/0x80 arch/x86/kernel/ldt.c:171 + destroy_context arch/x86/include/asm/mmu_context.h:157 [inline] + __mmdrop+0xe9/0x530 kernel/fork.c:889 + mmdrop include/linux/sched/mm.h:42 [inline] + exec_mmap fs/exec.c:1061 [inline] + flush_old_exec+0x173c/0x1ff0 fs/exec.c:1291 + load_elf_binary+0x81f/0x4ba0 fs/binfmt_elf.c:855 + search_binary_handler+0x142/0x6b0 fs/exec.c:1652 + exec_binprm fs/exec.c:1694 [inline] + do_execveat_common.isra.33+0x1746/0x22e0 fs/exec.c:1816 + do_execve+0x31/0x40 fs/exec.c:1860 + call_usermodehelper_exec_async+0x457/0x8f0 kernel/umh.c:100 + ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 + + Allocated by task 3700: + save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59 + save_stack+0x43/0xd0 mm/kasan/kasan.c:447 + set_track mm/kasan/kasan.c:459 [inline] + kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551 + kmem_cache_alloc_trace+0x136/0x750 mm/slab.c:3627 + kmalloc include/linux/slab.h:493 [inline] + alloc_ldt_struct+0x52/0x140 arch/x86/kernel/ldt.c:67 + write_ldt+0x7b7/0xab0 arch/x86/kernel/ldt.c:277 + sys_modify_ldt+0x1ef/0x240 arch/x86/kernel/ldt.c:307 + entry_SYSCALL_64_fastpath+0x1f/0xbe + + Freed by task 3700: + save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59 + save_stack+0x43/0xd0 mm/kasan/kasan.c:447 + set_track mm/kasan/kasan.c:459 [inline] + kasan_slab_free+0x71/0xc0 mm/kasan/kasan.c:524 + __cache_free mm/slab.c:3503 [inline] + kfree+0xca/0x250 mm/slab.c:3820 + free_ldt_struct.part.2+0xdd/0x150 arch/x86/kernel/ldt.c:121 + free_ldt_struct arch/x86/kernel/ldt.c:173 [inline] + destroy_context_ldt+0x60/0x80 arch/x86/kernel/ldt.c:171 + destroy_context arch/x86/include/asm/mmu_context.h:157 [inline] + __mmdrop+0xe9/0x530 kernel/fork.c:889 + mmdrop include/linux/sched/mm.h:42 [inline] + __mmput kernel/fork.c:916 [inline] + mmput+0x541/0x6e0 kernel/fork.c:927 + copy_process.part.36+0x22e1/0x4af0 kernel/fork.c:1931 + copy_process kernel/fork.c:1546 [inline] + _do_fork+0x1ef/0xfb0 kernel/fork.c:2025 + SYSC_clone kernel/fork.c:2135 [inline] + SyS_clone+0x37/0x50 kernel/fork.c:2129 + do_syscall_64+0x26c/0x8c0 arch/x86/entry/common.c:287 + return_from_SYSCALL_64+0x0/0x7a + +Here is a C reproducer: + + #include + #include + #include + #include + #include + #include + #include + + static void *fork_thread(void *_arg) + { + fork(); + } + + int main(void) + { + struct user_desc desc = { .entry_number = 8191 }; + + syscall(__NR_modify_ldt, 1, &desc, sizeof(desc)); + + for (;;) { + if (fork() == 0) { + pthread_t t; + + srand(getpid()); + pthread_create(&t, NULL, fork_thread, NULL); + usleep(rand() % 10000); + syscall(__NR_exit_group, 0); + } + wait(NULL); + } + } + +Note: the reproducer takes advantage of the fact that alloc_ldt_struct() +may use vmalloc() to allocate a large ->entries array, and after +commit: + + 5d17a73a2ebe ("vmalloc: back off when the current task is killed") + +it is possible for userspace to fail a task's vmalloc() by +sending a fatal signal, e.g. via exit_group(). It would be more +difficult to reproduce this bug on kernels without that commit. + +This bug only affected kernels with CONFIG_MODIFY_LDT_SYSCALL=y. + +Signed-off-by: Eric Biggers +Acked-by: Dave Hansen +Cc: [v4.6+] +Cc: Andrew Morton +Cc: Andy Lutomirski +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: Christoph Hellwig +Cc: Denys Vlasenko +Cc: Dmitry Vyukov +Cc: Linus Torvalds +Cc: Michal Hocko +Cc: Peter Zijlstra +Cc: Rik van Riel +Cc: Tetsuo Handa +Cc: Thomas Gleixner +Cc: linux-mm@kvack.org +Fixes: 39a0526fb3f7 ("x86/mm: Factor out LDT init from context init") +Link: http://lkml.kernel.org/r/20170824175029.76040-1-ebiggers3@gmail.com +Signed-off-by: Ingo Molnar +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/mmu_context.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/arch/x86/include/asm/mmu_context.h ++++ b/arch/x86/include/asm/mmu_context.h +@@ -109,8 +109,7 @@ static inline int init_new_context(struc + struct mm_struct *mm) + { + mm->context.ctx_id = atomic64_inc_return(&last_mm_ctx_id); +- init_new_context_ldt(tsk, mm); +- return 0; ++ return init_new_context_ldt(tsk, mm); + } + static inline void destroy_context(struct mm_struct *mm) + {