From: Greg Kroah-Hartman Date: Mon, 19 Nov 2018 13:00:40 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.19.3~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c596ad0065fe357ff78f62a46551f47b48abcf7c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: arch-alpha-termios-implement-bother-ibshift-and-termios2.patch btrfs-fix-cur_offset-in-the-error-case-for-nocow.patch btrfs-fix-data-corruption-due-to-cloning-of-eof-block.patch clockevents-drivers-i8253-add-support-for-pit-shutdown-quirk.patch configfs-replace-strncpy-with-memcpy.patch ext4-add-missing-brelse-add_new_gdb_meta_bg-s-error-path.patch ext4-add-missing-brelse-in-set_flexbg_block_bitmap-s-error-path.patch ext4-add-missing-brelse-update_backups-s-error-path.patch ext4-avoid-buffer-leak-in-ext4_orphan_add-after-prior-errors.patch ext4-avoid-possible-double-brelse-in-add_new_gdb-on-error-path.patch ext4-avoid-potential-extra-brelse-in-setup_new_flex_group_blocks.patch ext4-fix-buffer-leak-in-__ext4_read_dirblock-on-error-path.patch ext4-fix-buffer-leak-in-ext4_xattr_move_to_block-on-error-path.patch ext4-fix-missing-cleanup-if-ext4_alloc_flex_bg_array-fails-while-resizing.patch ext4-fix-possible-inode-leak-in-the-retry-loop-of-ext4_resize_fs.patch ext4-fix-possible-leak-of-s_journal_flag_rwsem-in-error-path.patch ext4-fix-possible-leak-of-sbi-s_group_desc_leak-in-error-path.patch ext4-release-bs.bh-before-re-using-in-ext4_xattr_block_find.patch fuse-fix-leaked-notify-reply.patch fuse-fix-use-after-free-in-fuse_direct_io.patch hugetlbfs-fix-kernel-bug-at-fs-hugetlbfs-inode.c-444.patch lib-ubsan.c-don-t-mark-__ubsan_handle_builtin_unreachable-as-noreturn.patch mm-migration-fix-migration-of-huge-pmd-shared-pages.patch mount-don-t-allow-copying-mnt_unbindable-mnt_locked-mounts.patch mount-prevent-mnt_detach-from-disconnecting-locked-mounts.patch mount-retest-mnt_locked-in-do_umount.patch nfsd-copy-and-clone-operations-require-the-saved-filehandle-to-be-set.patch rtc-hctosys-add-missing-range-error-reporting.patch sunrpc-correct-the-computation-for-page_ptr-when-truncating.patch termios-tty-tty_baudrate.c-fix-buffer-overrun.patch --- diff --git a/queue-4.9/arch-alpha-termios-implement-bother-ibshift-and-termios2.patch b/queue-4.9/arch-alpha-termios-implement-bother-ibshift-and-termios2.patch new file mode 100644 index 00000000000..b59750c0cfa --- /dev/null +++ b/queue-4.9/arch-alpha-termios-implement-bother-ibshift-and-termios2.patch @@ -0,0 +1,121 @@ +From d0ffb805b729322626639336986bc83fc2e60871 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin (Intel)" +Date: Mon, 22 Oct 2018 09:19:05 -0700 +Subject: arch/alpha, termios: implement BOTHER, IBSHIFT and termios2 + +From: H. Peter Anvin (Intel) + +commit d0ffb805b729322626639336986bc83fc2e60871 upstream. + +Alpha has had c_ispeed and c_ospeed, but still set speeds in c_cflags +using arbitrary flags. Because BOTHER is not defined, the general +Linux code doesn't allow setting arbitrary baud rates, and because +CBAUDEX == 0, we can have an array overrun of the baud_rate[] table in +drivers/tty/tty_baudrate.c if (c_cflags & CBAUD) == 037. + +Resolve both problems by #defining BOTHER to 037 on Alpha. + +However, userspace still needs to know if setting BOTHER is actually +safe given legacy kernels (does anyone actually care about that on +Alpha anymore?), so enable the TCGETS2/TCSETS*2 ioctls on Alpha, even +though they use the same structure. Define struct termios2 just for +compatibility; it is the exact same structure as struct termios. In a +future patchset, this will be cleaned up so the uapi headers are +usable from libc. + +Signed-off-by: H. Peter Anvin (Intel) +Cc: Jiri Slaby +Cc: Al Viro +Cc: Richard Henderson +Cc: Ivan Kokshaysky +Cc: Matt Turner +Cc: Thomas Gleixner +Cc: Kate Stewart +Cc: Philippe Ombredanne +Cc: Eugene Syromiatnikov +Cc: +Cc: +Cc: Johan Hovold +Cc: Alan Cox +Cc: +Signed-off-by: Greg Kroah-Hartman + +--- + arch/alpha/include/asm/termios.h | 8 +++++++- + arch/alpha/include/uapi/asm/ioctls.h | 5 +++++ + arch/alpha/include/uapi/asm/termbits.h | 17 +++++++++++++++++ + 3 files changed, 29 insertions(+), 1 deletion(-) + +--- a/arch/alpha/include/asm/termios.h ++++ b/arch/alpha/include/asm/termios.h +@@ -72,9 +72,15 @@ + }) + + #define user_termios_to_kernel_termios(k, u) \ +- copy_from_user(k, u, sizeof(struct termios)) ++ copy_from_user(k, u, sizeof(struct termios2)) + + #define kernel_termios_to_user_termios(u, k) \ ++ copy_to_user(u, k, sizeof(struct termios2)) ++ ++#define user_termios_to_kernel_termios_1(k, u) \ ++ copy_from_user(k, u, sizeof(struct termios)) ++ ++#define kernel_termios_to_user_termios_1(u, k) \ + copy_to_user(u, k, sizeof(struct termios)) + + #endif /* _ALPHA_TERMIOS_H */ +--- a/arch/alpha/include/uapi/asm/ioctls.h ++++ b/arch/alpha/include/uapi/asm/ioctls.h +@@ -31,6 +31,11 @@ + #define TCXONC _IO('t', 30) + #define TCFLSH _IO('t', 31) + ++#define TCGETS2 _IOR('T', 42, struct termios2) ++#define TCSETS2 _IOW('T', 43, struct termios2) ++#define TCSETSW2 _IOW('T', 44, struct termios2) ++#define TCSETSF2 _IOW('T', 45, struct termios2) ++ + #define TIOCSWINSZ _IOW('t', 103, struct winsize) + #define TIOCGWINSZ _IOR('t', 104, struct winsize) + #define TIOCSTART _IO('t', 110) /* start output, like ^Q */ +--- a/arch/alpha/include/uapi/asm/termbits.h ++++ b/arch/alpha/include/uapi/asm/termbits.h +@@ -25,6 +25,19 @@ struct termios { + speed_t c_ospeed; /* output speed */ + }; + ++/* Alpha has identical termios and termios2 */ ++ ++struct termios2 { ++ tcflag_t c_iflag; /* input mode flags */ ++ tcflag_t c_oflag; /* output mode flags */ ++ tcflag_t c_cflag; /* control mode flags */ ++ tcflag_t c_lflag; /* local mode flags */ ++ cc_t c_cc[NCCS]; /* control characters */ ++ cc_t c_line; /* line discipline (== c_cc[19]) */ ++ speed_t c_ispeed; /* input speed */ ++ speed_t c_ospeed; /* output speed */ ++}; ++ + /* Alpha has matching termios and ktermios */ + + struct ktermios { +@@ -147,6 +160,7 @@ struct ktermios { + #define B3000000 00034 + #define B3500000 00035 + #define B4000000 00036 ++#define BOTHER 00037 + + #define CSIZE 00001400 + #define CS5 00000000 +@@ -164,6 +178,9 @@ struct ktermios { + #define CMSPAR 010000000000 /* mark or space (stick) parity */ + #define CRTSCTS 020000000000 /* flow control */ + ++#define CIBAUD 07600000 ++#define IBSHIFT 16 ++ + /* c_lflag bits */ + #define ISIG 0x00000080 + #define ICANON 0x00000100 diff --git a/queue-4.9/btrfs-fix-cur_offset-in-the-error-case-for-nocow.patch b/queue-4.9/btrfs-fix-cur_offset-in-the-error-case-for-nocow.patch new file mode 100644 index 00000000000..04d68b95f99 --- /dev/null +++ b/queue-4.9/btrfs-fix-cur_offset-in-the-error-case-for-nocow.patch @@ -0,0 +1,77 @@ +From 506481b20e818db40b6198815904ecd2d6daee64 Mon Sep 17 00:00:00 2001 +From: Robbie Ko +Date: Tue, 30 Oct 2018 18:04:04 +0800 +Subject: Btrfs: fix cur_offset in the error case for nocow + +From: Robbie Ko + +commit 506481b20e818db40b6198815904ecd2d6daee64 upstream. + +When the cow_file_range fails, the related resources are unlocked +according to the range [start..end), so the unlock cannot be repeated in +run_delalloc_nocow. + +In some cases (e.g. cur_offset <= end && cow_start != -1), cur_offset is +not updated correctly, so move the cur_offset update before +cow_file_range. + + kernel BUG at mm/page-writeback.c:2663! + Internal error: Oops - BUG: 0 [#1] SMP + CPU: 3 PID: 31525 Comm: kworker/u8:7 Tainted: P O + Hardware name: Realtek_RTD1296 (DT) + Workqueue: writeback wb_workfn (flush-btrfs-1) + task: ffffffc076db3380 ti: ffffffc02e9ac000 task.ti: ffffffc02e9ac000 + PC is at clear_page_dirty_for_io+0x1bc/0x1e8 + LR is at clear_page_dirty_for_io+0x14/0x1e8 + pc : [] lr : [] pstate: 40000145 + sp : ffffffc02e9af4f0 + Process kworker/u8:7 (pid: 31525, stack limit = 0xffffffc02e9ac020) + Call trace: + [] clear_page_dirty_for_io+0x1bc/0x1e8 + [] extent_clear_unlock_delalloc+0x1e4/0x210 [btrfs] + [] run_delalloc_nocow+0x3b8/0x948 [btrfs] + [] run_delalloc_range+0x250/0x3a8 [btrfs] + [] writepage_delalloc.isra.21+0xbc/0x1d8 [btrfs] + [] __extent_writepage+0xe8/0x248 [btrfs] + [] extent_write_cache_pages.isra.17+0x164/0x378 [btrfs] + [] extent_writepages+0x48/0x68 [btrfs] + [] btrfs_writepages+0x20/0x30 [btrfs] + [] do_writepages+0x30/0x88 + [] __writeback_single_inode+0x34/0x198 + [] writeback_sb_inodes+0x184/0x3c0 + [] __writeback_inodes_wb+0x6c/0xc0 + [] wb_writeback+0x1b8/0x1c0 + [] wb_workfn+0x150/0x250 + [] process_one_work+0x1dc/0x388 + [] worker_thread+0x130/0x500 + [] kthread+0x10c/0x110 + [] ret_from_fork+0x10/0x40 + Code: d503201f a9025bb5 a90363b7 f90023b9 (d4210000) + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Filipe Manana +Signed-off-by: Robbie Ko +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/inode.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -1548,12 +1548,11 @@ out_check: + } + btrfs_release_path(path); + +- if (cur_offset <= end && cow_start == (u64)-1) { ++ if (cur_offset <= end && cow_start == (u64)-1) + cow_start = cur_offset; +- cur_offset = end; +- } + + if (cow_start != (u64)-1) { ++ cur_offset = end; + ret = cow_file_range(inode, locked_page, cow_start, end, end, + page_started, nr_written, 1, NULL); + if (ret) diff --git a/queue-4.9/btrfs-fix-data-corruption-due-to-cloning-of-eof-block.patch b/queue-4.9/btrfs-fix-data-corruption-due-to-cloning-of-eof-block.patch new file mode 100644 index 00000000000..7147afb3ab8 --- /dev/null +++ b/queue-4.9/btrfs-fix-data-corruption-due-to-cloning-of-eof-block.patch @@ -0,0 +1,98 @@ +From ac765f83f1397646c11092a032d4f62c3d478b81 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 5 Nov 2018 11:14:17 +0000 +Subject: Btrfs: fix data corruption due to cloning of eof block + +From: Filipe Manana + +commit ac765f83f1397646c11092a032d4f62c3d478b81 upstream. + +We currently allow cloning a range from a file which includes the last +block of the file even if the file's size is not aligned to the block +size. This is fine and useful when the destination file has the same size, +but when it does not and the range ends somewhere in the middle of the +destination file, it leads to corruption because the bytes between the EOF +and the end of the block have undefined data (when there is support for +discard/trimming they have a value of 0x00). + +Example: + + $ mkfs.btrfs -f /dev/sdb + $ mount /dev/sdb /mnt + + $ export foo_size=$((256 * 1024 + 100)) + $ xfs_io -f -c "pwrite -S 0x3c 0 $foo_size" /mnt/foo + $ xfs_io -f -c "pwrite -S 0xb5 0 1M" /mnt/bar + + $ xfs_io -c "reflink /mnt/foo 0 512K $foo_size" /mnt/bar + + $ od -A d -t x1 /mnt/bar + 0000000 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 + * + 0524288 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c + * + 0786528 3c 3c 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 + 0786544 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * + 0790528 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 + * + 1048576 + +The bytes in the range from 786532 (512Kb + 256Kb + 100 bytes) to 790527 +(512Kb + 256Kb + 4Kb - 1) got corrupted, having now a value of 0x00 instead +of 0xb5. + +This is similar to the problem we had for deduplication that got recently +fixed by commit de02b9f6bb65 ("Btrfs: fix data corruption when +deduplicating between different files"). + +Fix this by not allowing such operations to be performed and return the +errno -EINVAL to user space. This is what XFS is doing as well at the VFS +level. This change however now makes us return -EINVAL instead of +-EOPNOTSUPP for cases where the source range maps to an inline extent and +the destination range's end is smaller then the destination file's size, +since the detection of inline extents is done during the actual process of +dropping file extent items (at __btrfs_drop_extents()). Returning the +-EINVAL error is done early on and solely based on the input parameters +(offsets and length) and destination file's size. This makes us consistent +with XFS and anyone else supporting cloning since this case is now checked +at a higher level in the VFS and is where the -EINVAL will be returned +from starting with kernel 4.20 (the VFS changed was introduced in 4.20-rc1 +by commit 07d19dc9fbe9 ("vfs: avoid problematic remapping requests into +partial EOF block"). So this change is more geared towards stable kernels, +as it's unlikely the new VFS checks get removed intentionally. + +A test case for fstests follows soon, as well as an update to filter +existing tests that expect -EOPNOTSUPP to accept -EINVAL as well. + +CC: # 4.4+ +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ioctl.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -3911,9 +3911,17 @@ static noinline int btrfs_clone_files(st + goto out_unlock; + if (len == 0) + olen = len = src->i_size - off; +- /* if we extend to eof, continue to block boundary */ +- if (off + len == src->i_size) ++ /* ++ * If we extend to eof, continue to block boundary if and only if the ++ * destination end offset matches the destination file's size, otherwise ++ * we would be corrupting data by placing the eof block into the middle ++ * of a file. ++ */ ++ if (off + len == src->i_size) { ++ if (!IS_ALIGNED(len, bs) && destoff + len < inode->i_size) ++ goto out_unlock; + len = ALIGN(src->i_size, bs) - off; ++ } + + if (len == 0) { + ret = 0; diff --git a/queue-4.9/clockevents-drivers-i8253-add-support-for-pit-shutdown-quirk.patch b/queue-4.9/clockevents-drivers-i8253-add-support-for-pit-shutdown-quirk.patch new file mode 100644 index 00000000000..826a7d15ec7 --- /dev/null +++ b/queue-4.9/clockevents-drivers-i8253-add-support-for-pit-shutdown-quirk.patch @@ -0,0 +1,79 @@ +From 35b69a420bfb56b7b74cb635ea903db05e357bec Mon Sep 17 00:00:00 2001 +From: Michael Kelley +Date: Sun, 4 Nov 2018 03:48:54 +0000 +Subject: clockevents/drivers/i8253: Add support for PIT shutdown quirk + +From: Michael Kelley + +commit 35b69a420bfb56b7b74cb635ea903db05e357bec upstream. + +Add support for platforms where pit_shutdown() doesn't work because of a +quirk in the PIT emulation. On these platforms setting the counter register +to zero causes the PIT to start running again, negating the shutdown. + +Provide a global variable that controls whether the counter register is +zero'ed, which platform specific code can override. + +Signed-off-by: Michael Kelley +Signed-off-by: Thomas Gleixner +Cc: "gregkh@linuxfoundation.org" +Cc: "devel@linuxdriverproject.org" +Cc: "daniel.lezcano@linaro.org" +Cc: "virtualization@lists.linux-foundation.org" +Cc: "jgross@suse.com" +Cc: "akataria@vmware.com" +Cc: "olaf@aepfle.de" +Cc: "apw@canonical.com" +Cc: vkuznets +Cc: "jasowang@redhat.com" +Cc: "marcelo.cerri@canonical.com" +Cc: KY Srinivasan +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/1541303219-11142-2-git-send-email-mikelley@microsoft.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/clocksource/i8253.c | 14 ++++++++++++-- + include/linux/i8253.h | 1 + + 2 files changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/clocksource/i8253.c ++++ b/drivers/clocksource/i8253.c +@@ -19,6 +19,13 @@ + DEFINE_RAW_SPINLOCK(i8253_lock); + EXPORT_SYMBOL(i8253_lock); + ++/* ++ * Handle PIT quirk in pit_shutdown() where zeroing the counter register ++ * restarts the PIT, negating the shutdown. On platforms with the quirk, ++ * platform specific code can set this to false. ++ */ ++bool i8253_clear_counter_on_shutdown __ro_after_init = true; ++ + #ifdef CONFIG_CLKSRC_I8253 + /* + * Since the PIT overflows every tick, its not very useful +@@ -108,8 +115,11 @@ static int pit_shutdown(struct clock_eve + raw_spin_lock(&i8253_lock); + + outb_p(0x30, PIT_MODE); +- outb_p(0, PIT_CH0); +- outb_p(0, PIT_CH0); ++ ++ if (i8253_clear_counter_on_shutdown) { ++ outb_p(0, PIT_CH0); ++ outb_p(0, PIT_CH0); ++ } + + raw_spin_unlock(&i8253_lock); + return 0; +--- a/include/linux/i8253.h ++++ b/include/linux/i8253.h +@@ -21,6 +21,7 @@ + #define PIT_LATCH ((PIT_TICK_RATE + HZ/2) / HZ) + + extern raw_spinlock_t i8253_lock; ++extern bool i8253_clear_counter_on_shutdown; + extern struct clock_event_device i8253_clockevent; + extern void clockevent_i8253_init(bool oneshot); + diff --git a/queue-4.9/configfs-replace-strncpy-with-memcpy.patch b/queue-4.9/configfs-replace-strncpy-with-memcpy.patch new file mode 100644 index 00000000000..788c75115ec --- /dev/null +++ b/queue-4.9/configfs-replace-strncpy-with-memcpy.patch @@ -0,0 +1,41 @@ +From 1823342a1f2b47a4e6f5667f67cd28ab6bc4d6cd Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 1 Jul 2018 13:56:54 -0700 +Subject: configfs: replace strncpy with memcpy + +From: Guenter Roeck + +commit 1823342a1f2b47a4e6f5667f67cd28ab6bc4d6cd upstream. + +gcc 8.1.0 complains: + +fs/configfs/symlink.c:67:3: warning: + 'strncpy' output truncated before terminating nul copying as many + bytes from a string as its length +fs/configfs/symlink.c: In function 'configfs_get_link': +fs/configfs/symlink.c:63:13: note: length computed here + +Using strncpy() is indeed less than perfect since the length of data to +be copied has already been determined with strlen(). Replace strncpy() +with memcpy() to address the warning and optimize the code a little. + +Signed-off-by: Guenter Roeck +Signed-off-by: Christoph Hellwig +Signed-off-by: Nobuhiro Iwamatsu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/configfs/symlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/configfs/symlink.c ++++ b/fs/configfs/symlink.c +@@ -64,7 +64,7 @@ static void fill_item_path(struct config + + /* back up enough to print this bus id with '/' */ + length -= cur; +- strncpy(buffer + length,config_item_name(p),cur); ++ memcpy(buffer + length, config_item_name(p), cur); + *(buffer + --length) = '/'; + } + } diff --git a/queue-4.9/ext4-add-missing-brelse-add_new_gdb_meta_bg-s-error-path.patch b/queue-4.9/ext4-add-missing-brelse-add_new_gdb_meta_bg-s-error-path.patch new file mode 100644 index 00000000000..8dffe5fa85b --- /dev/null +++ b/queue-4.9/ext4-add-missing-brelse-add_new_gdb_meta_bg-s-error-path.patch @@ -0,0 +1,38 @@ +From 61a9c11e5e7a0dab5381afa5d9d4dd5ebf18f7a0 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Sat, 3 Nov 2018 16:50:08 -0400 +Subject: ext4: add missing brelse() add_new_gdb_meta_bg()'s error path + +From: Vasily Averin + +commit 61a9c11e5e7a0dab5381afa5d9d4dd5ebf18f7a0 upstream. + +Fixes: 01f795f9e0d6 ("ext4: add online resizing support for meta_bg ...") +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 3.7 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -899,6 +899,7 @@ static int add_new_gdb_meta_bg(struct su + sizeof(struct buffer_head *), + GFP_NOFS); + if (!n_group_desc) { ++ brelse(gdb_bh); + err = -ENOMEM; + ext4_warning(sb, "not enough memory for %lu groups", + gdb_num + 1); +@@ -914,8 +915,6 @@ static int add_new_gdb_meta_bg(struct su + kvfree(o_group_desc); + BUFFER_TRACE(gdb_bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, gdb_bh); +- if (unlikely(err)) +- brelse(gdb_bh); + return err; + } + diff --git a/queue-4.9/ext4-add-missing-brelse-in-set_flexbg_block_bitmap-s-error-path.patch b/queue-4.9/ext4-add-missing-brelse-in-set_flexbg_block_bitmap-s-error-path.patch new file mode 100644 index 00000000000..b403edce3eb --- /dev/null +++ b/queue-4.9/ext4-add-missing-brelse-in-set_flexbg_block_bitmap-s-error-path.patch @@ -0,0 +1,42 @@ +From cea5794122125bf67559906a0762186cf417099c Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Sat, 3 Nov 2018 16:22:10 -0400 +Subject: ext4: add missing brelse() in set_flexbg_block_bitmap()'s error path + +From: Vasily Averin + +commit cea5794122125bf67559906a0762186cf417099c upstream. + +Fixes: 33afdcc5402d ("ext4: add a function which sets up group blocks ...") +Cc: stable@kernel.org # 3.3 +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -442,16 +442,18 @@ static int set_flexbg_block_bitmap(struc + + BUFFER_TRACE(bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, bh); +- if (err) ++ if (err) { ++ brelse(bh); + return err; ++ } + ext4_debug("mark block bitmap %#04llx (+%llu/%u)\n", block, + block - start, count2); + ext4_set_bits(bh->b_data, block - start, count2); + + err = ext4_handle_dirty_metadata(handle, NULL, bh); ++ brelse(bh); + if (unlikely(err)) + return err; +- brelse(bh); + } + + return 0; diff --git a/queue-4.9/ext4-add-missing-brelse-update_backups-s-error-path.patch b/queue-4.9/ext4-add-missing-brelse-update_backups-s-error-path.patch new file mode 100644 index 00000000000..44393a563ed --- /dev/null +++ b/queue-4.9/ext4-add-missing-brelse-update_backups-s-error-path.patch @@ -0,0 +1,33 @@ +From ea0abbb648452cdb6e1734b702b6330a7448fcf8 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Sat, 3 Nov 2018 17:11:19 -0400 +Subject: ext4: add missing brelse() update_backups()'s error path + +From: Vasily Averin + +commit ea0abbb648452cdb6e1734b702b6330a7448fcf8 upstream. + +Fixes: ac27a0ec112a ("ext4: initial copy of files from ext3") +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 2.6.19 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1095,8 +1095,10 @@ static void update_backups(struct super_ + backup_block, backup_block - + ext4_group_first_block_no(sb, group)); + BUFFER_TRACE(bh, "get_write_access"); +- if ((err = ext4_journal_get_write_access(handle, bh))) ++ if ((err = ext4_journal_get_write_access(handle, bh))) { ++ brelse(bh); + break; ++ } + lock_buffer(bh); + memcpy(bh->b_data, data, size); + if (rest) diff --git a/queue-4.9/ext4-avoid-buffer-leak-in-ext4_orphan_add-after-prior-errors.patch b/queue-4.9/ext4-avoid-buffer-leak-in-ext4_orphan_add-after-prior-errors.patch new file mode 100644 index 00000000000..1bacbfebd5d --- /dev/null +++ b/queue-4.9/ext4-avoid-buffer-leak-in-ext4_orphan_add-after-prior-errors.patch @@ -0,0 +1,34 @@ +From feaf264ce7f8d54582e2f66eb82dd9dd124c94f3 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Tue, 6 Nov 2018 17:01:36 -0500 +Subject: ext4: avoid buffer leak in ext4_orphan_add() after prior errors + +From: Vasily Averin + +commit feaf264ce7f8d54582e2f66eb82dd9dd124c94f3 upstream. + +Fixes: d745a8c20c1f ("ext4: reduce contention on s_orphan_lock") +Fixes: 6e3617e579e0 ("ext4: Handle non empty on-disk orphan link") +Cc: Dmitry Monakhov +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 2.6.34 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2842,7 +2842,9 @@ int ext4_orphan_add(handle_t *handle, st + list_del_init(&EXT4_I(inode)->i_orphan); + mutex_unlock(&sbi->s_orphan_lock); + } +- } ++ } else ++ brelse(iloc.bh); ++ + jbd_debug(4, "superblock will point to %lu\n", inode->i_ino); + jbd_debug(4, "orphan inode %lu will point to %d\n", + inode->i_ino, NEXT_ORPHAN(inode)); diff --git a/queue-4.9/ext4-avoid-possible-double-brelse-in-add_new_gdb-on-error-path.patch b/queue-4.9/ext4-avoid-possible-double-brelse-in-add_new_gdb-on-error-path.patch new file mode 100644 index 00000000000..64dd413c7c8 --- /dev/null +++ b/queue-4.9/ext4-avoid-possible-double-brelse-in-add_new_gdb-on-error-path.patch @@ -0,0 +1,29 @@ +From 4f32c38b4662312dd3c5f113d8bdd459887fb773 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Tue, 6 Nov 2018 17:18:17 -0500 +Subject: ext4: avoid possible double brelse() in add_new_gdb() on error path + +From: Theodore Ts'o + +commit 4f32c38b4662312dd3c5f113d8bdd459887fb773 upstream. + +Fixes: b40971426a83 ("ext4: add error checking to calls to ...") +Reported-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 2.6.38 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -844,6 +844,7 @@ static int add_new_gdb(handle_t *handle, + err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh); + if (unlikely(err)) { + ext4_std_error(sb, err); ++ iloc.bh = NULL; + goto exit_inode; + } + brelse(dind); diff --git a/queue-4.9/ext4-avoid-potential-extra-brelse-in-setup_new_flex_group_blocks.patch b/queue-4.9/ext4-avoid-potential-extra-brelse-in-setup_new_flex_group_blocks.patch new file mode 100644 index 00000000000..9fbb80046e0 --- /dev/null +++ b/queue-4.9/ext4-avoid-potential-extra-brelse-in-setup_new_flex_group_blocks.patch @@ -0,0 +1,76 @@ +From 9e4028935cca3f9ef9b6a90df9da6f1f94853536 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Sat, 3 Nov 2018 16:13:17 -0400 +Subject: ext4: avoid potential extra brelse in setup_new_flex_group_blocks() + +From: Vasily Averin + +commit 9e4028935cca3f9ef9b6a90df9da6f1f94853536 upstream. + +Currently bh is set to NULL only during first iteration of for cycle, +then this pointer is not cleared after end of using. +Therefore rollback after errors can lead to extra brelse(bh) call, +decrements bh counter and later trigger an unexpected warning in __brelse() + +Patch moves brelse() calls in body of cycle to exclude requirement of +brelse() call in rollback. + +Fixes: 33afdcc5402d ("ext4: add a function which sets up group blocks ...") +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 3.3+ +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -590,7 +590,6 @@ handle_bb: + bh = bclean(handle, sb, block); + if (IS_ERR(bh)) { + err = PTR_ERR(bh); +- bh = NULL; + goto out; + } + overhead = ext4_group_overhead_blocks(sb, group); +@@ -602,9 +601,9 @@ handle_bb: + ext4_mark_bitmap_end(group_data[i].blocks_count, + sb->s_blocksize * 8, bh->b_data); + err = ext4_handle_dirty_metadata(handle, NULL, bh); ++ brelse(bh); + if (err) + goto out; +- brelse(bh); + + handle_ib: + if (bg_flags[i] & EXT4_BG_INODE_UNINIT) +@@ -619,18 +618,16 @@ handle_ib: + bh = bclean(handle, sb, block); + if (IS_ERR(bh)) { + err = PTR_ERR(bh); +- bh = NULL; + goto out; + } + + ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), + sb->s_blocksize * 8, bh->b_data); + err = ext4_handle_dirty_metadata(handle, NULL, bh); ++ brelse(bh); + if (err) + goto out; +- brelse(bh); + } +- bh = NULL; + + /* Mark group tables in block bitmap */ + for (j = 0; j < GROUP_TABLE_COUNT; j++) { +@@ -661,7 +658,6 @@ handle_ib: + } + + out: +- brelse(bh); + err2 = ext4_journal_stop(handle); + if (err2 && !err) + err = err2; diff --git a/queue-4.9/ext4-fix-buffer-leak-in-__ext4_read_dirblock-on-error-path.patch b/queue-4.9/ext4-fix-buffer-leak-in-__ext4_read_dirblock-on-error-path.patch new file mode 100644 index 00000000000..5c50c0be181 --- /dev/null +++ b/queue-4.9/ext4-fix-buffer-leak-in-__ext4_read_dirblock-on-error-path.patch @@ -0,0 +1,29 @@ +From de59fae0043f07de5d25e02ca360f7d57bfa5866 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Wed, 7 Nov 2018 22:36:23 -0500 +Subject: ext4: fix buffer leak in __ext4_read_dirblock() on error path + +From: Vasily Averin + +commit de59fae0043f07de5d25e02ca360f7d57bfa5866 upstream. + +Fixes: dc6982ff4db1 ("ext4: refactor code to read directory blocks ...") +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 3.9 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -124,6 +124,7 @@ static struct buffer_head *__ext4_read_d + if (!is_dx_block && type == INDEX) { + ext4_error_inode(inode, func, line, block, + "directory leaf block found instead of index block"); ++ brelse(bh); + return ERR_PTR(-EFSCORRUPTED); + } + if (!ext4_has_metadata_csum(inode->i_sb) || diff --git a/queue-4.9/ext4-fix-buffer-leak-in-ext4_xattr_move_to_block-on-error-path.patch b/queue-4.9/ext4-fix-buffer-leak-in-ext4_xattr_move_to_block-on-error-path.patch new file mode 100644 index 00000000000..a96d54802a7 --- /dev/null +++ b/queue-4.9/ext4-fix-buffer-leak-in-ext4_xattr_move_to_block-on-error-path.patch @@ -0,0 +1,32 @@ +From 6bdc9977fcdedf47118d2caf7270a19f4b6d8a8f Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Wed, 7 Nov 2018 11:10:21 -0500 +Subject: ext4: fix buffer leak in ext4_xattr_move_to_block() on error path + +From: Vasily Averin + +commit 6bdc9977fcdedf47118d2caf7270a19f4b6d8a8f upstream. + +Fixes: 3f2571c1f91f ("ext4: factor out xattr moving") +Fixes: 6dd4ee7cab7e ("ext4: Expand extra_inodes space per ...") +Reviewed-by: Jan Kara +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 2.6.23 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/xattr.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1393,6 +1393,8 @@ out: + kfree(buffer); + if (is) + brelse(is->iloc.bh); ++ if (bs) ++ brelse(bs->bh); + kfree(is); + kfree(bs); + diff --git a/queue-4.9/ext4-fix-missing-cleanup-if-ext4_alloc_flex_bg_array-fails-while-resizing.patch b/queue-4.9/ext4-fix-missing-cleanup-if-ext4_alloc_flex_bg_array-fails-while-resizing.patch new file mode 100644 index 00000000000..f91cf17c04f --- /dev/null +++ b/queue-4.9/ext4-fix-missing-cleanup-if-ext4_alloc_flex_bg_array-fails-while-resizing.patch @@ -0,0 +1,30 @@ +From f348e2241fb73515d65b5d77dd9c174128a7fbf2 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Tue, 6 Nov 2018 16:16:01 -0500 +Subject: ext4: fix missing cleanup if ext4_alloc_flex_bg_array() fails while resizing + +From: Vasily Averin + +commit f348e2241fb73515d65b5d77dd9c174128a7fbf2 upstream. + +Fixes: 117fff10d7f1 ("ext4: grow the s_flex_groups array as needed ...") +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 3.7 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1990,7 +1990,7 @@ retry: + + err = ext4_alloc_flex_bg_array(sb, n_group + 1); + if (err) +- return err; ++ goto out; + + err = ext4_mb_alloc_groupinfo(sb, n_group + 1); + if (err) diff --git a/queue-4.9/ext4-fix-possible-inode-leak-in-the-retry-loop-of-ext4_resize_fs.patch b/queue-4.9/ext4-fix-possible-inode-leak-in-the-retry-loop-of-ext4_resize_fs.patch new file mode 100644 index 00000000000..bb0b1b4f89c --- /dev/null +++ b/queue-4.9/ext4-fix-possible-inode-leak-in-the-retry-loop-of-ext4_resize_fs.patch @@ -0,0 +1,32 @@ +From db6aee62406d9fbb53315fcddd81f1dc271d49fa Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Tue, 6 Nov 2018 16:20:40 -0500 +Subject: ext4: fix possible inode leak in the retry loop of ext4_resize_fs() + +From: Vasily Averin + +commit db6aee62406d9fbb53315fcddd81f1dc271d49fa upstream. + +Fixes: 1c6bd7173d66 ("ext4: convert file system to meta_bg if needed ...") +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 3.7 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -2026,6 +2026,10 @@ retry: + n_blocks_count_retry = 0; + free_flex_gd(flex_gd); + flex_gd = NULL; ++ if (resize_inode) { ++ iput(resize_inode); ++ resize_inode = NULL; ++ } + goto retry; + } + diff --git a/queue-4.9/ext4-fix-possible-leak-of-s_journal_flag_rwsem-in-error-path.patch b/queue-4.9/ext4-fix-possible-leak-of-s_journal_flag_rwsem-in-error-path.patch new file mode 100644 index 00000000000..13fda81d21b --- /dev/null +++ b/queue-4.9/ext4-fix-possible-leak-of-s_journal_flag_rwsem-in-error-path.patch @@ -0,0 +1,29 @@ +From af18e35bfd01e6d65a5e3ef84ffe8b252d1628c5 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Wed, 7 Nov 2018 10:56:28 -0500 +Subject: ext4: fix possible leak of s_journal_flag_rwsem in error path + +From: Vasily Averin + +commit af18e35bfd01e6d65a5e3ef84ffe8b252d1628c5 upstream. + +Fixes: c8585c6fcaf2 ("ext4: fix races between changing inode journal ...") +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 4.7 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4305,6 +4305,7 @@ failed_mount6: + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); + percpu_counter_destroy(&sbi->s_dirtyclusters_counter); ++ percpu_free_rwsem(&sbi->s_journal_flag_rwsem); + failed_mount5: + ext4_ext_release(sb); + ext4_release_system_zone(sb); diff --git a/queue-4.9/ext4-fix-possible-leak-of-sbi-s_group_desc_leak-in-error-path.patch b/queue-4.9/ext4-fix-possible-leak-of-sbi-s_group_desc_leak-in-error-path.patch new file mode 100644 index 00000000000..cecf0a3b88e --- /dev/null +++ b/queue-4.9/ext4-fix-possible-leak-of-sbi-s_group_desc_leak-in-error-path.patch @@ -0,0 +1,51 @@ +From 9e463084cdb22e0b56b2dfbc50461020409a5fd3 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 7 Nov 2018 10:32:53 -0500 +Subject: ext4: fix possible leak of sbi->s_group_desc_leak in error path + +From: Theodore Ts'o + +commit 9e463084cdb22e0b56b2dfbc50461020409a5fd3 upstream. + +Fixes: bfe0a5f47ada ("ext4: add more mount time checks of the superblock") +Reported-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 4.18 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3897,6 +3897,14 @@ static int ext4_fill_super(struct super_ + sbi->s_groups_count = blocks_count; + sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count, + (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb))); ++ if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) != ++ le32_to_cpu(es->s_inodes_count)) { ++ ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu", ++ le32_to_cpu(es->s_inodes_count), ++ ((u64)sbi->s_groups_count * sbi->s_inodes_per_group)); ++ ret = -EINVAL; ++ goto failed_mount; ++ } + db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / + EXT4_DESC_PER_BLOCK(sb); + if (ext4_has_feature_meta_bg(sb)) { +@@ -3916,14 +3924,6 @@ static int ext4_fill_super(struct super_ + ret = -ENOMEM; + goto failed_mount; + } +- if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) != +- le32_to_cpu(es->s_inodes_count)) { +- ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu", +- le32_to_cpu(es->s_inodes_count), +- ((u64)sbi->s_groups_count * sbi->s_inodes_per_group)); +- ret = -EINVAL; +- goto failed_mount; +- } + + bgl_lock_init(sbi->s_blockgroup_lock); + diff --git a/queue-4.9/ext4-release-bs.bh-before-re-using-in-ext4_xattr_block_find.patch b/queue-4.9/ext4-release-bs.bh-before-re-using-in-ext4_xattr_block_find.patch new file mode 100644 index 00000000000..5aebbd658a6 --- /dev/null +++ b/queue-4.9/ext4-release-bs.bh-before-re-using-in-ext4_xattr_block_find.patch @@ -0,0 +1,33 @@ +From 45ae932d246f721e6584430017176cbcadfde610 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Wed, 7 Nov 2018 11:07:01 -0500 +Subject: ext4: release bs.bh before re-using in ext4_xattr_block_find() + +From: Vasily Averin + +commit 45ae932d246f721e6584430017176cbcadfde610 upstream. + +bs.bh was taken in previous ext4_xattr_block_find() call, +it should be released before re-using + +Fixes: 7e01c8e5420b ("ext3/4: fix uninitialized bs in ...") +Signed-off-by: Vasily Averin +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org # 2.6.26 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/xattr.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1221,6 +1221,8 @@ ext4_xattr_set_handle(handle_t *handle, + error = ext4_xattr_block_set(handle, inode, &i, &bs); + } else if (error == -ENOSPC) { + if (EXT4_I(inode)->i_file_acl && !bs.s.base) { ++ brelse(bs.bh); ++ bs.bh = NULL; + error = ext4_xattr_block_find(inode, &i, &bs); + if (error) + goto cleanup; diff --git a/queue-4.9/fuse-fix-leaked-notify-reply.patch b/queue-4.9/fuse-fix-leaked-notify-reply.patch new file mode 100644 index 00000000000..f2e73b8fcbc --- /dev/null +++ b/queue-4.9/fuse-fix-leaked-notify-reply.patch @@ -0,0 +1,40 @@ +From 7fabaf303458fcabb694999d6fa772cc13d4e217 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Fri, 9 Nov 2018 15:52:16 +0100 +Subject: fuse: fix leaked notify reply + +From: Miklos Szeredi + +commit 7fabaf303458fcabb694999d6fa772cc13d4e217 upstream. + +fuse_request_send_notify_reply() may fail if the connection was reset for +some reason (e.g. fs was unmounted). Don't leak request reference in this +case. Besides leaking memory, this resulted in fc->num_waiting not being +decremented and hence fuse_wait_aborted() left in a hanging and unkillable +state. + +Fixes: 2d45ba381a74 ("fuse: add retrieve request") +Fixes: b8f95e5d13f5 ("fuse: umount should wait for all requests") +Reported-and-tested-by: syzbot+6339eda9cb4ebbc4c37b@syzkaller.appspotmail.com +Signed-off-by: Miklos Szeredi +Cc: #v2.6.36 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1715,8 +1715,10 @@ static int fuse_retrieve(struct fuse_con + req->in.args[1].size = total_len; + + err = fuse_request_send_notify_reply(fc, req, outarg->notify_unique); +- if (err) ++ if (err) { + fuse_retrieve_end(fc, req); ++ fuse_put_request(fc, req); ++ } + + return err; + } diff --git a/queue-4.9/fuse-fix-use-after-free-in-fuse_direct_io.patch b/queue-4.9/fuse-fix-use-after-free-in-fuse_direct_io.patch new file mode 100644 index 00000000000..1352e901d5d --- /dev/null +++ b/queue-4.9/fuse-fix-use-after-free-in-fuse_direct_io.patch @@ -0,0 +1,45 @@ +From ebacb81273599555a7a19f7754a1451206a5fc4f Mon Sep 17 00:00:00 2001 +From: Lukas Czerner +Date: Fri, 9 Nov 2018 14:51:46 +0100 +Subject: fuse: fix use-after-free in fuse_direct_IO() + +From: Lukas Czerner + +commit ebacb81273599555a7a19f7754a1451206a5fc4f upstream. + +In async IO blocking case the additional reference to the io is taken for +it to survive fuse_aio_complete(). In non blocking case this additional +reference is not needed, however we still reference io to figure out +whether to wait for completion or not. This is wrong and will lead to +use-after-free. Fix it by storing blocking information in separate +variable. + +This was spotted by KASAN when running generic/208 fstest. + +Signed-off-by: Lukas Czerner +Reported-by: Zorro Lang +Signed-off-by: Miklos Szeredi +Fixes: 744742d692e3 ("fuse: Add reference counting for fuse_io_priv") +Cc: # v4.6 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/file.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -2900,10 +2900,12 @@ fuse_direct_IO(struct kiocb *iocb, struc + } + + if (io->async) { ++ bool blocking = io->blocking; ++ + fuse_aio_complete(io, ret < 0 ? ret : 0, -1); + + /* we have a non-extending, async request, so return */ +- if (!io->blocking) ++ if (!blocking) + return -EIOCBQUEUED; + + wait_for_completion(&wait); diff --git a/queue-4.9/hugetlbfs-fix-kernel-bug-at-fs-hugetlbfs-inode.c-444.patch b/queue-4.9/hugetlbfs-fix-kernel-bug-at-fs-hugetlbfs-inode.c-444.patch new file mode 100644 index 00000000000..675b55aa37b --- /dev/null +++ b/queue-4.9/hugetlbfs-fix-kernel-bug-at-fs-hugetlbfs-inode.c-444.patch @@ -0,0 +1,133 @@ +From 5e41540c8a0f0e98c337dda8b391e5dda0cde7cf Mon Sep 17 00:00:00 2001 +From: Mike Kravetz +Date: Fri, 16 Nov 2018 15:08:04 -0800 +Subject: hugetlbfs: fix kernel BUG at fs/hugetlbfs/inode.c:444! + +From: Mike Kravetz + +commit 5e41540c8a0f0e98c337dda8b391e5dda0cde7cf upstream. + +This bug has been experienced several times by the Oracle DB team. The +BUG is in remove_inode_hugepages() as follows: + + /* + * If page is mapped, it was faulted in after being + * unmapped in caller. Unmap (again) now after taking + * the fault mutex. The mutex will prevent faults + * until we finish removing the page. + * + * This race can only happen in the hole punch case. + * Getting here in a truncate operation is a bug. + */ + if (unlikely(page_mapped(page))) { + BUG_ON(truncate_op); + +In this case, the elevated map count is not the result of a race. +Rather it was incorrectly incremented as the result of a bug in the huge +pmd sharing code. Consider the following: + + - Process A maps a hugetlbfs file of sufficient size and alignment + (PUD_SIZE) that a pmd page could be shared. + + - Process B maps the same hugetlbfs file with the same size and + alignment such that a pmd page is shared. + + - Process B then calls mprotect() to change protections for the mapping + with the shared pmd. As a result, the pmd is 'unshared'. + + - Process B then calls mprotect() again to chage protections for the + mapping back to their original value. pmd remains unshared. + + - Process B then forks and process C is created. During the fork + process, we do dup_mm -> dup_mmap -> copy_page_range to copy page + tables. Copying page tables for hugetlb mappings is done in the + routine copy_hugetlb_page_range. + +In copy_hugetlb_page_range(), the destination pte is obtained by: + + dst_pte = huge_pte_alloc(dst, addr, sz); + +If pmd sharing is possible, the returned pointer will be to a pte in an +existing page table. In the situation above, process C could share with +either process A or process B. Since process A is first in the list, +the returned pte is a pointer to a pte in process A's page table. + +However, the check for pmd sharing in copy_hugetlb_page_range is: + + /* If the pagetables are shared don't copy or take references */ + if (dst_pte == src_pte) + continue; + +Since process C is sharing with process A instead of process B, the +above test fails. The code in copy_hugetlb_page_range which follows +assumes dst_pte points to a huge_pte_none pte. It copies the pte entry +from src_pte to dst_pte and increments this map count of the associated +page. This is how we end up with an elevated map count. + +To solve, check the dst_pte entry for huge_pte_none. If !none, this +implies PMD sharing so do not copy. + +Link: http://lkml.kernel.org/r/20181105212315.14125-1-mike.kravetz@oracle.com +Fixes: c5c99429fa57 ("fix hugepages leak due to pagetable page sharing") +Signed-off-by: Mike Kravetz +Reviewed-by: Naoya Horiguchi +Cc: Michal Hocko +Cc: Hugh Dickins +Cc: Andrea Arcangeli +Cc: "Kirill A . Shutemov" +Cc: Davidlohr Bueso +Cc: Prakash Sangappa +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/hugetlb.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -3220,7 +3220,7 @@ static int is_hugetlb_entry_hwpoisoned(p + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, + struct vm_area_struct *vma) + { +- pte_t *src_pte, *dst_pte, entry; ++ pte_t *src_pte, *dst_pte, entry, dst_entry; + struct page *ptepage; + unsigned long addr; + int cow; +@@ -3248,15 +3248,30 @@ int copy_hugetlb_page_range(struct mm_st + break; + } + +- /* If the pagetables are shared don't copy or take references */ +- if (dst_pte == src_pte) ++ /* ++ * If the pagetables are shared don't copy or take references. ++ * dst_pte == src_pte is the common case of src/dest sharing. ++ * ++ * However, src could have 'unshared' and dst shares with ++ * another vma. If dst_pte !none, this implies sharing. ++ * Check here before taking page table lock, and once again ++ * after taking the lock below. ++ */ ++ dst_entry = huge_ptep_get(dst_pte); ++ if ((dst_pte == src_pte) || !huge_pte_none(dst_entry)) + continue; + + dst_ptl = huge_pte_lock(h, dst, dst_pte); + src_ptl = huge_pte_lockptr(h, src, src_pte); + spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING); + entry = huge_ptep_get(src_pte); +- if (huge_pte_none(entry)) { /* skip none entry */ ++ dst_entry = huge_ptep_get(dst_pte); ++ if (huge_pte_none(entry) || !huge_pte_none(dst_entry)) { ++ /* ++ * Skip if src entry none. Also, skip in the ++ * unlikely case dst entry !none as this implies ++ * sharing with another vma. ++ */ + ; + } else if (unlikely(is_hugetlb_entry_migration(entry) || + is_hugetlb_entry_hwpoisoned(entry))) { diff --git a/queue-4.9/lib-ubsan.c-don-t-mark-__ubsan_handle_builtin_unreachable-as-noreturn.patch b/queue-4.9/lib-ubsan.c-don-t-mark-__ubsan_handle_builtin_unreachable-as-noreturn.patch new file mode 100644 index 00000000000..1c85064b90f --- /dev/null +++ b/queue-4.9/lib-ubsan.c-don-t-mark-__ubsan_handle_builtin_unreachable-as-noreturn.patch @@ -0,0 +1,47 @@ +From 1c23b4108d716cc848b38532063a8aca4f86add8 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Fri, 16 Nov 2018 15:08:35 -0800 +Subject: lib/ubsan.c: don't mark __ubsan_handle_builtin_unreachable as noreturn + +From: Arnd Bergmann + +commit 1c23b4108d716cc848b38532063a8aca4f86add8 upstream. + +gcc-8 complains about the prototype for this function: + + lib/ubsan.c:432:1: error: ignoring attribute 'noreturn' in declaration of a built-in function '__ubsan_handle_builtin_unreachable' because it conflicts with attribute 'const' [-Werror=attributes] + +This is actually a GCC's bug. In GCC internals +__ubsan_handle_builtin_unreachable() declared with both 'noreturn' and +'const' attributes instead of only 'noreturn': + + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84210 + +Workaround this by removing the noreturn attribute. + +[aryabinin: add information about GCC bug in changelog] +Link: http://lkml.kernel.org/r/20181107144516.4587-1-aryabinin@virtuozzo.com +Signed-off-by: Arnd Bergmann +Signed-off-by: Andrey Ryabinin +Acked-by: Olof Johansson +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + lib/ubsan.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/lib/ubsan.c ++++ b/lib/ubsan.c +@@ -451,8 +451,7 @@ void __ubsan_handle_shift_out_of_bounds( + EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds); + + +-void __noreturn +-__ubsan_handle_builtin_unreachable(struct unreachable_data *data) ++void __ubsan_handle_builtin_unreachable(struct unreachable_data *data) + { + unsigned long flags; + diff --git a/queue-4.9/mm-migration-fix-migration-of-huge-pmd-shared-pages.patch b/queue-4.9/mm-migration-fix-migration-of-huge-pmd-shared-pages.patch new file mode 100644 index 00000000000..25734120004 --- /dev/null +++ b/queue-4.9/mm-migration-fix-migration-of-huge-pmd-shared-pages.patch @@ -0,0 +1,254 @@ +From 017b1660df89f5fb4bfe66c34e35f7d2031100c7 Mon Sep 17 00:00:00 2001 +From: Mike Kravetz +Date: Fri, 5 Oct 2018 15:51:29 -0700 +Subject: mm: migration: fix migration of huge PMD shared pages + +From: Mike Kravetz + +commit 017b1660df89f5fb4bfe66c34e35f7d2031100c7 upstream. + +The page migration code employs try_to_unmap() to try and unmap the source +page. This is accomplished by using rmap_walk to find all vmas where the +page is mapped. This search stops when page mapcount is zero. For shared +PMD huge pages, the page map count is always 1 no matter the number of +mappings. Shared mappings are tracked via the reference count of the PMD +page. Therefore, try_to_unmap stops prematurely and does not completely +unmap all mappings of the source page. + +This problem can result is data corruption as writes to the original +source page can happen after contents of the page are copied to the target +page. Hence, data is lost. + +This problem was originally seen as DB corruption of shared global areas +after a huge page was soft offlined due to ECC memory errors. DB +developers noticed they could reproduce the issue by (hotplug) offlining +memory used to back huge pages. A simple testcase can reproduce the +problem by creating a shared PMD mapping (note that this must be at least +PUD_SIZE in size and PUD_SIZE aligned (1GB on x86)), and using +migrate_pages() to migrate process pages between nodes while continually +writing to the huge pages being migrated. + +To fix, have the try_to_unmap_one routine check for huge PMD sharing by +calling huge_pmd_unshare for hugetlbfs huge pages. If it is a shared +mapping it will be 'unshared' which removes the page table entry and drops +the reference on the PMD page. After this, flush caches and TLB. + +mmu notifiers are called before locking page tables, but we can not be +sure of PMD sharing until page tables are locked. Therefore, check for +the possibility of PMD sharing before locking so that notifiers can +prepare for the worst possible case. + +Link: http://lkml.kernel.org/r/20180823205917.16297-2-mike.kravetz@oracle.com +[mike.kravetz@oracle.com: make _range_in_vma() a static inline] + Link: http://lkml.kernel.org/r/6063f215-a5c8-2f0c-465a-2c515ddc952d@oracle.com +Fixes: 39dde65c9940 ("shared page table for hugetlb page") +Signed-off-by: Mike Kravetz +Acked-by: Kirill A. Shutemov +Reviewed-by: Naoya Horiguchi +Acked-by: Michal Hocko +Cc: Vlastimil Babka +Cc: Davidlohr Bueso +Cc: Jerome Glisse +Cc: Mike Kravetz +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Mike Kravetz +Reviewed-by: Jérôme Glisse +Acked-by: Michal Hocko +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/hugetlb.h | 14 ++++++++++++ + include/linux/mm.h | 6 +++++ + mm/hugetlb.c | 37 ++++++++++++++++++++++++++++++- + mm/rmap.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 111 insertions(+), 2 deletions(-) + +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -109,6 +109,8 @@ pte_t *huge_pte_alloc(struct mm_struct * + unsigned long addr, unsigned long sz); + pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr); + int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep); ++void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma, ++ unsigned long *start, unsigned long *end); + struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, + int write); + struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, +@@ -131,6 +133,18 @@ static inline unsigned long hugetlb_tota + return 0; + } + ++static inline int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, ++ pte_t *ptep) ++{ ++ return 0; ++} ++ ++static inline void adjust_range_if_pmd_sharing_possible( ++ struct vm_area_struct *vma, ++ unsigned long *start, unsigned long *end) ++{ ++} ++ + #define follow_hugetlb_page(m,v,p,vs,a,b,i,w) ({ BUG(); 0; }) + #define follow_huge_addr(mm, addr, write) ERR_PTR(-EINVAL) + #define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; }) +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -2187,6 +2187,12 @@ static inline struct vm_area_struct *fin + return vma; + } + ++static inline bool range_in_vma(struct vm_area_struct *vma, ++ unsigned long start, unsigned long end) ++{ ++ return (vma && vma->vm_start <= start && end <= vma->vm_end); ++} ++ + #ifdef CONFIG_MMU + pgprot_t vm_get_page_prot(unsigned long vm_flags); + void vma_set_page_prot(struct vm_area_struct *vma); +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -4333,13 +4333,41 @@ static bool vma_shareable(struct vm_area + /* + * check on proper vm_flags and page table alignment + */ +- if (vma->vm_flags & VM_MAYSHARE && +- vma->vm_start <= base && end <= vma->vm_end) ++ if (vma->vm_flags & VM_MAYSHARE && range_in_vma(vma, base, end)) + return true; + return false; + } + + /* ++ * Determine if start,end range within vma could be mapped by shared pmd. ++ * If yes, adjust start and end to cover range associated with possible ++ * shared pmd mappings. ++ */ ++void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma, ++ unsigned long *start, unsigned long *end) ++{ ++ unsigned long check_addr = *start; ++ ++ if (!(vma->vm_flags & VM_MAYSHARE)) ++ return; ++ ++ for (check_addr = *start; check_addr < *end; check_addr += PUD_SIZE) { ++ unsigned long a_start = check_addr & PUD_MASK; ++ unsigned long a_end = a_start + PUD_SIZE; ++ ++ /* ++ * If sharing is possible, adjust start/end if necessary. ++ */ ++ if (range_in_vma(vma, a_start, a_end)) { ++ if (a_start < *start) ++ *start = a_start; ++ if (a_end > *end) ++ *end = a_end; ++ } ++ } ++} ++ ++/* + * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc() + * and returns the corresponding pte. While this is not necessary for the + * !shared pmd case because we can allocate the pmd later as well, it makes the +@@ -4435,6 +4463,11 @@ int huge_pmd_unshare(struct mm_struct *m + { + return 0; + } ++ ++void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma, ++ unsigned long *start, unsigned long *end) ++{ ++} + #define want_pmd_share() (0) + #endif /* CONFIG_ARCH_WANT_HUGE_PMD_SHARE */ + +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -1476,6 +1476,9 @@ static int try_to_unmap_one(struct page + pte_t pteval; + spinlock_t *ptl; + int ret = SWAP_AGAIN; ++ unsigned long sh_address; ++ bool pmd_sharing_possible = false; ++ unsigned long spmd_start, spmd_end; + struct rmap_private *rp = arg; + enum ttu_flags flags = rp->flags; + +@@ -1491,6 +1494,32 @@ static int try_to_unmap_one(struct page + goto out; + } + ++ /* ++ * Only use the range_start/end mmu notifiers if huge pmd sharing ++ * is possible. In the normal case, mmu_notifier_invalidate_page ++ * is sufficient as we only unmap a page. However, if we unshare ++ * a pmd, we will unmap a PUD_SIZE range. ++ */ ++ if (PageHuge(page)) { ++ spmd_start = address; ++ spmd_end = spmd_start + vma_mmu_pagesize(vma); ++ ++ /* ++ * Check if pmd sharing is possible. If possible, we could ++ * unmap a PUD_SIZE range. spmd_start/spmd_end will be ++ * modified if sharing is possible. ++ */ ++ adjust_range_if_pmd_sharing_possible(vma, &spmd_start, ++ &spmd_end); ++ if (spmd_end - spmd_start != vma_mmu_pagesize(vma)) { ++ sh_address = address; ++ ++ pmd_sharing_possible = true; ++ mmu_notifier_invalidate_range_start(vma->vm_mm, ++ spmd_start, spmd_end); ++ } ++ } ++ + pte = page_check_address(page, mm, address, &ptl, + PageTransCompound(page)); + if (!pte) +@@ -1524,6 +1553,30 @@ static int try_to_unmap_one(struct page + } + } + ++ /* ++ * Call huge_pmd_unshare to potentially unshare a huge pmd. Pass ++ * sh_address as it will be modified if unsharing is successful. ++ */ ++ if (PageHuge(page) && huge_pmd_unshare(mm, &sh_address, pte)) { ++ /* ++ * huge_pmd_unshare unmapped an entire PMD page. There is ++ * no way of knowing exactly which PMDs may be cached for ++ * this mm, so flush them all. spmd_start/spmd_end cover ++ * this PUD_SIZE range. ++ */ ++ flush_cache_range(vma, spmd_start, spmd_end); ++ flush_tlb_range(vma, spmd_start, spmd_end); ++ ++ /* ++ * The ref count of the PMD page was dropped which is part ++ * of the way map counting is done for shared PMDs. When ++ * there is no other sharing, huge_pmd_unshare returns false ++ * and we will unmap the actual page and drop map count ++ * to zero. ++ */ ++ goto out_unmap; ++ } ++ + /* Nuke the page table entry. */ + flush_cache_page(vma, address, page_to_pfn(page)); + if (should_defer_flush(mm, flags)) { +@@ -1621,6 +1674,9 @@ out_unmap: + if (ret != SWAP_FAIL && ret != SWAP_MLOCK && !(flags & TTU_MUNLOCK)) + mmu_notifier_invalidate_page(mm, address); + out: ++ if (pmd_sharing_possible) ++ mmu_notifier_invalidate_range_end(vma->vm_mm, ++ spmd_start, spmd_end); + return ret; + } + diff --git a/queue-4.9/mount-don-t-allow-copying-mnt_unbindable-mnt_locked-mounts.patch b/queue-4.9/mount-don-t-allow-copying-mnt_unbindable-mnt_locked-mounts.patch new file mode 100644 index 00000000000..0490f7bcfb5 --- /dev/null +++ b/queue-4.9/mount-don-t-allow-copying-mnt_unbindable-mnt_locked-mounts.patch @@ -0,0 +1,71 @@ +From df7342b240185d58d3d9665c0bbf0a0f5570ec29 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Thu, 25 Oct 2018 09:04:18 -0500 +Subject: mount: Don't allow copying MNT_UNBINDABLE|MNT_LOCKED mounts + +From: Eric W. Biederman + +commit df7342b240185d58d3d9665c0bbf0a0f5570ec29 upstream. + +Jonathan Calmels from NVIDIA reported that he's able to bypass the +mount visibility security check in place in the Linux kernel by using +a combination of the unbindable property along with the private mount +propagation option to allow a unprivileged user to see a path which +was purposefully hidden by the root user. + +Reproducer: + # Hide a path to all users using a tmpfs + root@castiana:~# mount -t tmpfs tmpfs /sys/devices/ + root@castiana:~# + + # As an unprivileged user, unshare user namespace and mount namespace + stgraber@castiana:~$ unshare -U -m -r + + # Confirm the path is still not accessible + root@castiana:~# ls /sys/devices/ + + # Make /sys recursively unbindable and private + root@castiana:~# mount --make-runbindable /sys + root@castiana:~# mount --make-private /sys + + # Recursively bind-mount the rest of /sys over to /mnnt + root@castiana:~# mount --rbind /sys/ /mnt + + # Access our hidden /sys/device as an unprivileged user + root@castiana:~# ls /mnt/devices/ + breakpoint cpu cstate_core cstate_pkg i915 intel_pt isa kprobe + LNXSYSTM:00 msr pci0000:00 platform pnp0 power software system + tracepoint uncore_arb uncore_cbox_0 uncore_cbox_1 uprobe virtual + +Solve this by teaching copy_tree to fail if a mount turns out to be +both unbindable and locked. + +Cc: stable@vger.kernel.org +Fixes: 5ff9d8a65ce8 ("vfs: Lock in place mounts from more privileged users") +Reported-by: Jonathan Calmels +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/namespace.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1788,8 +1788,14 @@ struct mount *copy_tree(struct mount *mn + for (s = r; s; s = next_mnt(s, r)) { + if (!(flag & CL_COPY_UNBINDABLE) && + IS_MNT_UNBINDABLE(s)) { +- s = skip_mnt_tree(s); +- continue; ++ if (s->mnt.mnt_flags & MNT_LOCKED) { ++ /* Both unbindable and locked. */ ++ q = ERR_PTR(-EPERM); ++ goto out; ++ } else { ++ s = skip_mnt_tree(s); ++ continue; ++ } + } + if (!(flag & CL_COPY_MNT_NS_FILE) && + is_mnt_ns_file(s->mnt.mnt_root)) { diff --git a/queue-4.9/mount-prevent-mnt_detach-from-disconnecting-locked-mounts.patch b/queue-4.9/mount-prevent-mnt_detach-from-disconnecting-locked-mounts.patch new file mode 100644 index 00000000000..3674ad82650 --- /dev/null +++ b/queue-4.9/mount-prevent-mnt_detach-from-disconnecting-locked-mounts.patch @@ -0,0 +1,105 @@ +From 9c8e0a1b683525464a2abe9fb4b54404a50ed2b4 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Thu, 25 Oct 2018 12:05:11 -0500 +Subject: mount: Prevent MNT_DETACH from disconnecting locked mounts + +From: Eric W. Biederman + +commit 9c8e0a1b683525464a2abe9fb4b54404a50ed2b4 upstream. + +Timothy Baldwin wrote: +> As per mount_namespaces(7) unprivileged users should not be able to look under mount points: +> +> Mounts that come as a single unit from more privileged mount are locked +> together and may not be separated in a less privileged mount namespace. +> +> However they can: +> +> 1. Create a mount namespace. +> 2. In the mount namespace open a file descriptor to the parent of a mount point. +> 3. Destroy the mount namespace. +> 4. Use the file descriptor to look under the mount point. +> +> I have reproduced this with Linux 4.16.18 and Linux 4.18-rc8. +> +> The setup: +> +> $ sudo sysctl kernel.unprivileged_userns_clone=1 +> kernel.unprivileged_userns_clone = 1 +> $ mkdir -p A/B/Secret +> $ sudo mount -t tmpfs hide A/B +> +> +> "Secret" is indeed hidden as expected: +> +> $ ls -lR A +> A: +> total 0 +> drwxrwxrwt 2 root root 40 Feb 12 21:08 B +> +> A/B: +> total 0 +> +> +> The attack revealing "Secret": +> +> $ unshare -Umr sh -c "exec unshare -m ls -lR /proc/self/fd/4/ 4 /proc/self/fd/4/: +> total 0 +> drwxr-xr-x 3 root root 60 Feb 12 21:08 B +> +> /proc/self/fd/4/B: +> total 0 +> drwxr-xr-x 2 root root 40 Feb 12 21:08 Secret +> +> /proc/self/fd/4/B/Secret: +> total 0 + +I tracked this down to put_mnt_ns running passing UMOUNT_SYNC and +disconnecting all of the mounts in a mount namespace. Fix this by +factoring drop_mounts out of drop_collected_mounts and passing +0 instead of UMOUNT_SYNC. + +There are two possible behavior differences that result from this. +- No longer setting UMOUNT_SYNC will no longer set MNT_SYNC_UMOUNT on + the vfsmounts being unmounted. This effects the lazy rcu walk by + kicking the walk out of rcu mode and forcing it to be a non-lazy + walk. +- No longer disconnecting locked mounts will keep some mounts around + longer as they stay because the are locked to other mounts. + +There are only two users of drop_collected mounts: audit_tree.c and +put_mnt_ns. + +In audit_tree.c the mounts are private and there are no rcu lazy walks +only calls to iterate_mounts. So the changes should have no effect +except for a small timing effect as the connected mounts are disconnected. + +In put_mnt_ns there may be references from process outside the mount +namespace to the mounts. So the mounts remaining connected will +be the bug fix that is needed. That rcu walks are allowed to continue +appears not to be a problem especially as the rcu walk change was about +an implementation detail not about semantics. + +Cc: stable@vger.kernel.org +Fixes: 5ff9d8a65ce8 ("vfs: Lock in place mounts from more privileged users") +Reported-by: Timothy Baldwin +Tested-by: Timothy Baldwin +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/namespace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1848,7 +1848,7 @@ void drop_collected_mounts(struct vfsmou + { + namespace_lock(); + lock_mount_hash(); +- umount_tree(real_mount(mnt), UMOUNT_SYNC); ++ umount_tree(real_mount(mnt), 0); + unlock_mount_hash(); + namespace_unlock(); + } diff --git a/queue-4.9/mount-retest-mnt_locked-in-do_umount.patch b/queue-4.9/mount-retest-mnt_locked-in-do_umount.patch new file mode 100644 index 00000000000..06ef6f45cc8 --- /dev/null +++ b/queue-4.9/mount-retest-mnt_locked-in-do_umount.patch @@ -0,0 +1,61 @@ +From 25d202ed820ee347edec0bf3bf553544556bf64b Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Mon, 22 Oct 2018 10:21:38 -0500 +Subject: mount: Retest MNT_LOCKED in do_umount + +From: Eric W. Biederman + +commit 25d202ed820ee347edec0bf3bf553544556bf64b upstream. + +It was recently pointed out that the one instance of testing MNT_LOCKED +outside of the namespace_sem is in ksys_umount. + +Fix that by adding a test inside of do_umount with namespace_sem and +the mount_lock held. As it helps to fail fails the existing test is +maintained with an additional comment pointing out that it may be racy +because the locks are not held. + +Cc: stable@vger.kernel.org +Reported-by: Al Viro +Fixes: 5ff9d8a65ce8 ("vfs: Lock in place mounts from more privileged users") +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/namespace.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1599,8 +1599,13 @@ static int do_umount(struct mount *mnt, + + namespace_lock(); + lock_mount_hash(); +- event++; + ++ /* Recheck MNT_LOCKED with the locks held */ ++ retval = -EINVAL; ++ if (mnt->mnt.mnt_flags & MNT_LOCKED) ++ goto out; ++ ++ event++; + if (flags & MNT_DETACH) { + if (!list_empty(&mnt->mnt_list)) + umount_tree(mnt, UMOUNT_PROPAGATE); +@@ -1614,6 +1619,7 @@ static int do_umount(struct mount *mnt, + retval = 0; + } + } ++out: + unlock_mount_hash(); + namespace_unlock(); + return retval; +@@ -1704,7 +1710,7 @@ SYSCALL_DEFINE2(umount, char __user *, n + goto dput_and_out; + if (!check_mnt(mnt)) + goto dput_and_out; +- if (mnt->mnt.mnt_flags & MNT_LOCKED) ++ if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */ + goto dput_and_out; + retval = -EPERM; + if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) diff --git a/queue-4.9/nfsd-copy-and-clone-operations-require-the-saved-filehandle-to-be-set.patch b/queue-4.9/nfsd-copy-and-clone-operations-require-the-saved-filehandle-to-be-set.patch new file mode 100644 index 00000000000..3f299d4756a --- /dev/null +++ b/queue-4.9/nfsd-copy-and-clone-operations-require-the-saved-filehandle-to-be-set.patch @@ -0,0 +1,33 @@ +From 01310bb7c9c98752cc763b36532fab028e0f8f81 Mon Sep 17 00:00:00 2001 +From: Scott Mayhew +Date: Thu, 8 Nov 2018 11:11:36 -0500 +Subject: nfsd: COPY and CLONE operations require the saved filehandle to be set + +From: Scott Mayhew + +commit 01310bb7c9c98752cc763b36532fab028e0f8f81 upstream. + +Make sure we have a saved filehandle, otherwise we'll oops with a null +pointer dereference in nfs4_preprocess_stateid_op(). + +Signed-off-by: Scott Mayhew +Cc: stable@vger.kernel.org +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4proc.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1016,6 +1016,9 @@ nfsd4_verify_copy(struct svc_rqst *rqstp + { + __be32 status; + ++ if (!cstate->save_fh.fh_dentry) ++ return nfserr_nofilehandle; ++ + status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh, + src_stateid, RD_STATE, src, NULL); + if (status) { diff --git a/queue-4.9/rtc-hctosys-add-missing-range-error-reporting.patch b/queue-4.9/rtc-hctosys-add-missing-range-error-reporting.patch new file mode 100644 index 00000000000..ee8f51380c9 --- /dev/null +++ b/queue-4.9/rtc-hctosys-add-missing-range-error-reporting.patch @@ -0,0 +1,42 @@ +From 7ce9a992ffde8ce93d5ae5767362a5c7389ae895 Mon Sep 17 00:00:00 2001 +From: "Maciej W. Rozycki" +Date: Mon, 5 Nov 2018 03:48:25 +0000 +Subject: rtc: hctosys: Add missing range error reporting + +From: Maciej W. Rozycki + +commit 7ce9a992ffde8ce93d5ae5767362a5c7389ae895 upstream. + +Fix an issue with the 32-bit range error path in `rtc_hctosys' where no +error code is set and consequently the successful preceding call result +from `rtc_read_time' is propagated to `rtc_hctosys_ret'. This in turn +makes any subsequent call to `hctosys_show' incorrectly report in sysfs +that the system time has been set from this RTC while it has not. + +Set the error to ERANGE then if we can't express the result due to an +overflow. + +Signed-off-by: Maciej W. Rozycki +Fixes: b3a5ac42ab18 ("rtc: hctosys: Ensure system time doesn't overflow time_t") +Cc: stable@vger.kernel.org # 4.17+ +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/rtc/hctosys.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/rtc/hctosys.c ++++ b/drivers/rtc/hctosys.c +@@ -50,8 +50,10 @@ static int __init rtc_hctosys(void) + tv64.tv_sec = rtc_tm_to_time64(&tm); + + #if BITS_PER_LONG == 32 +- if (tv64.tv_sec > INT_MAX) ++ if (tv64.tv_sec > INT_MAX) { ++ err = -ERANGE; + goto err_read; ++ } + #endif + + err = do_settimeofday64(&tv64); diff --git a/queue-4.9/series b/queue-4.9/series index 406c359ff99..0fb4f61e688 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -45,3 +45,33 @@ mm-thp-relax-__gfp_thisnode-for-madv_hugepage-mappings.patch netfilter-conntrack-fix-calculation-of-next-bucket-number-in-early_drop.patch mtd-docg3-don-t-set-conflicting-bch_const_params-option.patch of-numa-validate-some-distance-map-rules.patch +termios-tty-tty_baudrate.c-fix-buffer-overrun.patch +arch-alpha-termios-implement-bother-ibshift-and-termios2.patch +btrfs-fix-cur_offset-in-the-error-case-for-nocow.patch +btrfs-fix-data-corruption-due-to-cloning-of-eof-block.patch +clockevents-drivers-i8253-add-support-for-pit-shutdown-quirk.patch +ext4-add-missing-brelse-update_backups-s-error-path.patch +ext4-add-missing-brelse-in-set_flexbg_block_bitmap-s-error-path.patch +ext4-add-missing-brelse-add_new_gdb_meta_bg-s-error-path.patch +ext4-avoid-potential-extra-brelse-in-setup_new_flex_group_blocks.patch +ext4-fix-possible-inode-leak-in-the-retry-loop-of-ext4_resize_fs.patch +ext4-avoid-buffer-leak-in-ext4_orphan_add-after-prior-errors.patch +ext4-fix-missing-cleanup-if-ext4_alloc_flex_bg_array-fails-while-resizing.patch +ext4-avoid-possible-double-brelse-in-add_new_gdb-on-error-path.patch +ext4-fix-possible-leak-of-sbi-s_group_desc_leak-in-error-path.patch +ext4-fix-possible-leak-of-s_journal_flag_rwsem-in-error-path.patch +ext4-release-bs.bh-before-re-using-in-ext4_xattr_block_find.patch +ext4-fix-buffer-leak-in-ext4_xattr_move_to_block-on-error-path.patch +ext4-fix-buffer-leak-in-__ext4_read_dirblock-on-error-path.patch +mount-retest-mnt_locked-in-do_umount.patch +mount-don-t-allow-copying-mnt_unbindable-mnt_locked-mounts.patch +mount-prevent-mnt_detach-from-disconnecting-locked-mounts.patch +sunrpc-correct-the-computation-for-page_ptr-when-truncating.patch +nfsd-copy-and-clone-operations-require-the-saved-filehandle-to-be-set.patch +rtc-hctosys-add-missing-range-error-reporting.patch +fuse-fix-use-after-free-in-fuse_direct_io.patch +fuse-fix-leaked-notify-reply.patch +configfs-replace-strncpy-with-memcpy.patch +lib-ubsan.c-don-t-mark-__ubsan_handle_builtin_unreachable-as-noreturn.patch +hugetlbfs-fix-kernel-bug-at-fs-hugetlbfs-inode.c-444.patch +mm-migration-fix-migration-of-huge-pmd-shared-pages.patch diff --git a/queue-4.9/sunrpc-correct-the-computation-for-page_ptr-when-truncating.patch b/queue-4.9/sunrpc-correct-the-computation-for-page_ptr-when-truncating.patch new file mode 100644 index 00000000000..124b8fb3892 --- /dev/null +++ b/queue-4.9/sunrpc-correct-the-computation-for-page_ptr-when-truncating.patch @@ -0,0 +1,46 @@ +From 5d7a5bcb67c70cbc904057ef52d3fcfeb24420bb Mon Sep 17 00:00:00 2001 +From: Frank Sorenson +Date: Tue, 30 Oct 2018 15:10:40 -0500 +Subject: sunrpc: correct the computation for page_ptr when truncating + +From: Frank Sorenson + +commit 5d7a5bcb67c70cbc904057ef52d3fcfeb24420bb upstream. + +When truncating the encode buffer, the page_ptr is getting +advanced, causing the next page to be skipped while encoding. +The page is still included in the response, so the response +contains a page of bogus data. + +We need to adjust the page_ptr backwards to ensure we encode +the next page into the correct place. + +We saw this triggered when concurrent directory modifications caused +nfsd4_encode_direct_fattr() to return nfserr_noent, and the resulting +call to xdr_truncate_encode() corrupted the READDIR reply. + +Signed-off-by: Frank Sorenson +Cc: stable@vger.kernel.org +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/xdr.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/net/sunrpc/xdr.c ++++ b/net/sunrpc/xdr.c +@@ -639,11 +639,10 @@ void xdr_truncate_encode(struct xdr_stre + WARN_ON_ONCE(xdr->iov); + return; + } +- if (fraglen) { ++ if (fraglen) + xdr->end = head->iov_base + head->iov_len; +- xdr->page_ptr--; +- } + /* (otherwise assume xdr->end is already set) */ ++ xdr->page_ptr--; + head->iov_len = len; + buf->len = len; + xdr->p = head->iov_base + head->iov_len; diff --git a/queue-4.9/termios-tty-tty_baudrate.c-fix-buffer-overrun.patch b/queue-4.9/termios-tty-tty_baudrate.c-fix-buffer-overrun.patch new file mode 100644 index 00000000000..c3ec2adfa58 --- /dev/null +++ b/queue-4.9/termios-tty-tty_baudrate.c-fix-buffer-overrun.patch @@ -0,0 +1,55 @@ +From 991a25194097006ec1e0d2e0814ff920e59e3465 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Mon, 22 Oct 2018 09:19:04 -0700 +Subject: termios, tty/tty_baudrate.c: fix buffer overrun + +From: H. Peter Anvin + +commit 991a25194097006ec1e0d2e0814ff920e59e3465 upstream. + +On architectures with CBAUDEX == 0 (Alpha and PowerPC), the code in tty_baudrate.c does +not do any limit checking on the tty_baudrate[] array, and in fact a +buffer overrun is possible on both architectures. Add a limit check to +prevent that situation. + +This will be followed by a much bigger cleanup/simplification patch. + +Signed-off-by: H. Peter Anvin (Intel) +Requested-by: Cc: Johan Hovold +Cc: Jiri Slaby +Cc: Al Viro +Cc: Richard Henderson +Cc: Ivan Kokshaysky +Cc: Matt Turner +Cc: Thomas Gleixner +Cc: Kate Stewart +Cc: Philippe Ombredanne +Cc: Eugene Syromiatnikov +Cc: Alan Cox +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/tty_ioctl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/tty/tty_ioctl.c ++++ b/drivers/tty/tty_ioctl.c +@@ -325,7 +325,7 @@ speed_t tty_termios_baud_rate(struct kte + else + cbaud += 15; + } +- return baud_table[cbaud]; ++ return cbaud >= n_baud_table ? 0 : baud_table[cbaud]; + } + EXPORT_SYMBOL(tty_termios_baud_rate); + +@@ -361,7 +361,7 @@ speed_t tty_termios_input_baud_rate(stru + else + cbaud += 15; + } +- return baud_table[cbaud]; ++ return cbaud >= n_baud_table ? 0 : baud_table[cbaud]; + #else + return tty_termios_baud_rate(termios); + #endif