diff options
author | Thorsten Leemhuis <fedora@leemhuis.info> | 2016-05-07 00:12:20 +0200 |
---|---|---|
committer | Thorsten Leemhuis <fedora@leemhuis.info> | 2016-05-07 00:12:20 +0200 |
commit | 02f3c66fa79b3a567c61f6c795a54c0d752f62c7 (patch) | |
tree | 604d24c56d8bfc761e586d2a2cac6d73e08ea75f | |
parent | c6f688a1b8ed42af35d2d86d8dc4d4c05d55589b (diff) | |
parent | 29b09fa4d9724b89812c8d8b0240d35a45edab97 (diff) | |
download | kernel-02f3c66fa79b3a567c61f6c795a54c0d752f62c7.tar.gz kernel-02f3c66fa79b3a567c61f6c795a54c0d752f62c7.tar.xz kernel-02f3c66fa79b3a567c61f6c795a54c0d752f62c7.zip |
Merge remote-tracking branch 'origin/f22' into f22-user-thl-vanilla-fedorakernel-4.4.9-200.vanilla.knurd.1.fc22
-rw-r--r-- | USB-usbip-fix-potential-out-of-bounds-write.patch | 45 | ||||
-rw-r--r-- | ext4-fix-races-between-buffered-IO-and-collapse-inse.patch | 119 | ||||
-rw-r--r-- | ext4-fix-races-between-page-faults-and-hole-punching.patch | 442 | ||||
-rw-r--r-- | ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch | 110 | ||||
-rw-r--r-- | ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch | 93 | ||||
-rw-r--r-- | input-gtco-fix-crash-on-detecting-device-without-end.patch | 49 | ||||
-rw-r--r-- | kernel.spec | 55 | ||||
-rw-r--r-- | net-fix-infoleak-in-llc.patch | 32 | ||||
-rw-r--r-- | net-fix-infoleak-in-rtnetlink.patch | 50 | ||||
-rw-r--r-- | propogate_mnt-Handle-the-first-propogated-copy-being.patch | 146 | ||||
-rw-r--r-- | sources | 2 | ||||
-rw-r--r-- | x86-xen-suppress-hugetlbfs-in-PV-guests.patch | 70 |
12 files changed, 253 insertions, 960 deletions
diff --git a/USB-usbip-fix-potential-out-of-bounds-write.patch b/USB-usbip-fix-potential-out-of-bounds-write.patch deleted file mode 100644 index 3d9f7c294..000000000 --- a/USB-usbip-fix-potential-out-of-bounds-write.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b348d7dddb6c4fbfc810b7a0626e8ec9e29f7cbb Mon Sep 17 00:00:00 2001 -From: Ignat Korchagin <ignat.korchagin@gmail.com> -Date: Thu, 17 Mar 2016 18:00:29 +0000 -Subject: [PATCH] USB: usbip: fix potential out-of-bounds write - -Fix potential out-of-bounds write to urb->transfer_buffer -usbip handles network communication directly in the kernel. When receiving a -packet from its peer, usbip code parses headers according to protocol. As -part of this parsing urb->actual_length is filled. Since the input for -urb->actual_length comes from the network, it should be treated as untrusted. -Any entity controlling the network may put any value in the input and the -preallocated urb->transfer_buffer may not be large enough to hold the data. -Thus, the malicious entity is able to write arbitrary data to kernel memory. - -Signed-off-by: Ignat Korchagin <ignat.korchagin@gmail.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ---- - drivers/usb/usbip/usbip_common.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c -index facaaf003f19..e40da7759a0e 100644 ---- a/drivers/usb/usbip/usbip_common.c -+++ b/drivers/usb/usbip/usbip_common.c -@@ -741,6 +741,17 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) - if (!(size > 0)) - return 0; - -+ if (size > urb->transfer_buffer_length) { -+ /* should not happen, probably malicious packet */ -+ if (ud->side == USBIP_STUB) { -+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); -+ return 0; -+ } else { -+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); -+ return -EPIPE; -+ } -+ } -+ - ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size); - if (ret != size) { - dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret); --- -2.5.5 - diff --git a/ext4-fix-races-between-buffered-IO-and-collapse-inse.patch b/ext4-fix-races-between-buffered-IO-and-collapse-inse.patch deleted file mode 100644 index 0c89ea77a..000000000 --- a/ext4-fix-races-between-buffered-IO-and-collapse-inse.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 32ebffd3bbb4162da5ff88f9a35dd32d0a28ea70 Mon Sep 17 00:00:00 2001 -From: Jan Kara <jack@suse.com> -Date: Mon, 7 Dec 2015 14:31:11 -0500 -Subject: [PATCH 3/4] ext4: fix races between buffered IO and collapse / insert - range - -Current code implementing FALLOC_FL_COLLAPSE_RANGE and -FALLOC_FL_INSERT_RANGE is prone to races with buffered writes and page -faults. If buffered write or write via mmap manages to squeeze between -filemap_write_and_wait_range() and truncate_pagecache() in the fallocate -implementations, the written data is simply discarded by -truncate_pagecache() although it should have been shifted. - -Fix the problem by moving filemap_write_and_wait_range() call inside -i_mutex and i_mmap_sem. That way we are protected against races with -both buffered writes and page faults. - -Signed-off-by: Jan Kara <jack@suse.com> -Signed-off-by: Theodore Ts'o <tytso@mit.edu> ---- - fs/ext4/extents.c | 59 +++++++++++++++++++++++++++++-------------------------- - 1 file changed, 31 insertions(+), 28 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 65b5ada2833f..4b105c96df08 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -5487,21 +5487,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) - return ret; - } - -- /* -- * Need to round down offset to be aligned with page size boundary -- * for page size > block size. -- */ -- ioffset = round_down(offset, PAGE_SIZE); -- -- /* Write out all dirty pages */ -- ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, -- LLONG_MAX); -- if (ret) -- return ret; -- -- /* Take mutex lock */ - mutex_lock(&inode->i_mutex); -- - /* - * There is no need to overlap collapse range with EOF, in which case - * it is effectively a truncate operation -@@ -5526,6 +5512,27 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) - * page cache. - */ - down_write(&EXT4_I(inode)->i_mmap_sem); -+ /* -+ * Need to round down offset to be aligned with page size boundary -+ * for page size > block size. -+ */ -+ ioffset = round_down(offset, PAGE_SIZE); -+ /* -+ * Write tail of the last page before removed range since it will get -+ * removed from the page cache below. -+ */ -+ ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, offset); -+ if (ret) -+ goto out_mmap; -+ /* -+ * Write data that will be shifted to preserve them when discarding -+ * page cache below. We are also protected from pages becoming dirty -+ * by i_mmap_sem. -+ */ -+ ret = filemap_write_and_wait_range(inode->i_mapping, offset + len, -+ LLONG_MAX); -+ if (ret) -+ goto out_mmap; - truncate_pagecache(inode, ioffset); - - credits = ext4_writepage_trans_blocks(inode); -@@ -5626,21 +5633,7 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) - return ret; - } - -- /* -- * Need to round down to align start offset to page size boundary -- * for page size > block size. -- */ -- ioffset = round_down(offset, PAGE_SIZE); -- -- /* Write out all dirty pages */ -- ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, -- LLONG_MAX); -- if (ret) -- return ret; -- -- /* Take mutex lock */ - mutex_lock(&inode->i_mutex); -- - /* Currently just for extent based files */ - if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { - ret = -EOPNOTSUPP; -@@ -5668,6 +5661,16 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) - * page cache. - */ - down_write(&EXT4_I(inode)->i_mmap_sem); -+ /* -+ * Need to round down to align start offset to page size boundary -+ * for page size > block size. -+ */ -+ ioffset = round_down(offset, PAGE_SIZE); -+ /* Write out all dirty pages */ -+ ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, -+ LLONG_MAX); -+ if (ret) -+ goto out_mmap; - truncate_pagecache(inode, ioffset); - - credits = ext4_writepage_trans_blocks(inode); --- -2.5.5 - diff --git a/ext4-fix-races-between-page-faults-and-hole-punching.patch b/ext4-fix-races-between-page-faults-and-hole-punching.patch deleted file mode 100644 index 9034b958c..000000000 --- a/ext4-fix-races-between-page-faults-and-hole-punching.patch +++ /dev/null @@ -1,442 +0,0 @@ -From ea3d7209ca01da209cda6f0dea8be9cc4b7a933b Mon Sep 17 00:00:00 2001 -From: Jan Kara <jack@suse.com> -Date: Mon, 7 Dec 2015 14:28:03 -0500 -Subject: [PATCH 1/4] ext4: fix races between page faults and hole punching - -Currently, page faults and hole punching are completely unsynchronized. -This can result in page fault faulting in a page into a range that we -are punching after truncate_pagecache_range() has been called and thus -we can end up with a page mapped to disk blocks that will be shortly -freed. Filesystem corruption will shortly follow. Note that the same -race is avoided for truncate by checking page fault offset against -i_size but there isn't similar mechanism available for punching holes. - -Fix the problem by creating new rw semaphore i_mmap_sem in inode and -grab it for writing over truncate, hole punching, and other functions -removing blocks from extent tree and for read over page faults. We -cannot easily use i_data_sem for this since that ranks below transaction -start and we need something ranking above it so that it can be held over -the whole truncate / hole punching operation. Also remove various -workarounds we had in the code to reduce race window when page fault -could have created pages with stale mapping information. - -Signed-off-by: Jan Kara <jack@suse.com> -Signed-off-by: Theodore Ts'o <tytso@mit.edu> ---- - fs/ext4/ext4.h | 10 +++++++++ - fs/ext4/extents.c | 54 ++++++++++++++++++++++++-------------------- - fs/ext4/file.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++-------- - fs/ext4/inode.c | 36 +++++++++++++++++++++-------- - fs/ext4/super.c | 1 + - fs/ext4/truncate.h | 2 ++ - 6 files changed, 127 insertions(+), 42 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index cc7ca4e87144..348a5ff4a0e2 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -910,6 +910,15 @@ struct ext4_inode_info { - * by other means, so we have i_data_sem. - */ - struct rw_semaphore i_data_sem; -+ /* -+ * i_mmap_sem is for serializing page faults with truncate / punch hole -+ * operations. We have to make sure that new page cannot be faulted in -+ * a section of the inode that is being punched. We cannot easily use -+ * i_data_sem for this since we need protection for the whole punch -+ * operation and i_data_sem ranks below transaction start so we have -+ * to occasionally drop it. -+ */ -+ struct rw_semaphore i_mmap_sem; - struct inode vfs_inode; - struct jbd2_inode *jinode; - -@@ -2484,6 +2493,7 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); - extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode, - loff_t lstart, loff_t lend); - extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); -+extern int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf); - extern qsize_t *ext4_get_reserved_space(struct inode *inode); - extern void ext4_da_update_reserve_space(struct inode *inode, - int used, int quota_claim); -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 551353b1b17a..5be9ca5a8a7a 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4770,7 +4770,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, - int partial_begin, partial_end; - loff_t start, end; - ext4_lblk_t lblk; -- struct address_space *mapping = inode->i_mapping; - unsigned int blkbits = inode->i_blkbits; - - trace_ext4_zero_range(inode, offset, len, mode); -@@ -4786,17 +4785,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, - } - - /* -- * Write out all dirty pages to avoid race conditions -- * Then release them. -- */ -- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { -- ret = filemap_write_and_wait_range(mapping, offset, -- offset + len - 1); -- if (ret) -- return ret; -- } -- -- /* - * Round up offset. This is not fallocate, we neet to zero out - * blocks, so convert interior block aligned part of the range to - * unwritten and possibly manually zero out unaligned parts of the -@@ -4856,16 +4844,22 @@ static long ext4_zero_range(struct file *file, loff_t offset, - flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | - EXT4_EX_NOCACHE); - -- /* Now release the pages and zero block aligned part of pages*/ -- truncate_pagecache_range(inode, start, end - 1); -- inode->i_mtime = inode->i_ctime = ext4_current_time(inode); -- - /* Wait all existing dio workers, newcomers will block on i_mutex */ - ext4_inode_block_unlocked_dio(inode); - inode_dio_wait(inode); - -+ /* -+ * Prevent page faults from reinstantiating pages we have -+ * released from page cache. -+ */ -+ down_write(&EXT4_I(inode)->i_mmap_sem); -+ /* Now release the pages and zero block aligned part of pages */ -+ truncate_pagecache_range(inode, start, end - 1); -+ inode->i_mtime = inode->i_ctime = ext4_current_time(inode); -+ - ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, - flags, mode); -+ up_write(&EXT4_I(inode)->i_mmap_sem); - if (ret) - goto out_dio; - } -@@ -5524,17 +5518,22 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) - goto out_mutex; - } - -- truncate_pagecache(inode, ioffset); -- - /* Wait for existing dio to complete */ - ext4_inode_block_unlocked_dio(inode); - inode_dio_wait(inode); - -+ /* -+ * Prevent page faults from reinstantiating pages we have released from -+ * page cache. -+ */ -+ down_write(&EXT4_I(inode)->i_mmap_sem); -+ truncate_pagecache(inode, ioffset); -+ - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); -- goto out_dio; -+ goto out_mmap; - } - - down_write(&EXT4_I(inode)->i_data_sem); -@@ -5573,7 +5572,8 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) - - out_stop: - ext4_journal_stop(handle); --out_dio: -+out_mmap: -+ up_write(&EXT4_I(inode)->i_mmap_sem); - ext4_inode_resume_unlocked_dio(inode); - out_mutex: - mutex_unlock(&inode->i_mutex); -@@ -5660,17 +5660,22 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) - goto out_mutex; - } - -- truncate_pagecache(inode, ioffset); -- - /* Wait for existing dio to complete */ - ext4_inode_block_unlocked_dio(inode); - inode_dio_wait(inode); - -+ /* -+ * Prevent page faults from reinstantiating pages we have released from -+ * page cache. -+ */ -+ down_write(&EXT4_I(inode)->i_mmap_sem); -+ truncate_pagecache(inode, ioffset); -+ - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); -- goto out_dio; -+ goto out_mmap; - } - - /* Expand file to avoid data loss if there is error while shifting */ -@@ -5741,7 +5746,8 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) - - out_stop: - ext4_journal_stop(handle); --out_dio: -+out_mmap: -+ up_write(&EXT4_I(inode)->i_mmap_sem); - ext4_inode_resume_unlocked_dio(inode); - out_mutex: - mutex_unlock(&inode->i_mutex); -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 113837e7ba98..0d24ebcd7c9e 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -209,15 +209,18 @@ static int ext4_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf) - { - int result; - handle_t *handle = NULL; -- struct super_block *sb = file_inode(vma->vm_file)->i_sb; -+ struct inode *inode = file_inode(vma->vm_file); -+ struct super_block *sb = inode->i_sb; - bool write = vmf->flags & FAULT_FLAG_WRITE; - - if (write) { - sb_start_pagefault(sb); - file_update_time(vma->vm_file); -+ down_read(&EXT4_I(inode)->i_mmap_sem); - handle = ext4_journal_start_sb(sb, EXT4_HT_WRITE_PAGE, - EXT4_DATA_TRANS_BLOCKS(sb)); -- } -+ } else -+ down_read(&EXT4_I(inode)->i_mmap_sem); - - if (IS_ERR(handle)) - result = VM_FAULT_SIGBUS; -@@ -228,8 +231,10 @@ static int ext4_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf) - if (write) { - if (!IS_ERR(handle)) - ext4_journal_stop(handle); -+ up_read(&EXT4_I(inode)->i_mmap_sem); - sb_end_pagefault(sb); -- } -+ } else -+ up_read(&EXT4_I(inode)->i_mmap_sem); - - return result; - } -@@ -246,10 +251,12 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, - if (write) { - sb_start_pagefault(sb); - file_update_time(vma->vm_file); -+ down_read(&EXT4_I(inode)->i_mmap_sem); - handle = ext4_journal_start_sb(sb, EXT4_HT_WRITE_PAGE, - ext4_chunk_trans_blocks(inode, - PMD_SIZE / PAGE_SIZE)); -- } -+ } else -+ down_read(&EXT4_I(inode)->i_mmap_sem); - - if (IS_ERR(handle)) - result = VM_FAULT_SIGBUS; -@@ -260,30 +267,71 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, - if (write) { - if (!IS_ERR(handle)) - ext4_journal_stop(handle); -+ up_read(&EXT4_I(inode)->i_mmap_sem); - sb_end_pagefault(sb); -- } -+ } else -+ up_read(&EXT4_I(inode)->i_mmap_sem); - - return result; - } - - static int ext4_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) - { -- return dax_mkwrite(vma, vmf, ext4_get_block_dax, -- ext4_end_io_unwritten); -+ int err; -+ struct inode *inode = file_inode(vma->vm_file); -+ -+ sb_start_pagefault(inode->i_sb); -+ file_update_time(vma->vm_file); -+ down_read(&EXT4_I(inode)->i_mmap_sem); -+ err = __dax_mkwrite(vma, vmf, ext4_get_block_dax, -+ ext4_end_io_unwritten); -+ up_read(&EXT4_I(inode)->i_mmap_sem); -+ sb_end_pagefault(inode->i_sb); -+ -+ return err; -+} -+ -+/* -+ * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_mkwrite() -+ * handler we check for races agaist truncate. Note that since we cycle through -+ * i_mmap_sem, we are sure that also any hole punching that began before we -+ * were called is finished by now and so if it included part of the file we -+ * are working on, our pte will get unmapped and the check for pte_same() in -+ * wp_pfn_shared() fails. Thus fault gets retried and things work out as -+ * desired. -+ */ -+static int ext4_dax_pfn_mkwrite(struct vm_area_struct *vma, -+ struct vm_fault *vmf) -+{ -+ struct inode *inode = file_inode(vma->vm_file); -+ struct super_block *sb = inode->i_sb; -+ int ret = VM_FAULT_NOPAGE; -+ loff_t size; -+ -+ sb_start_pagefault(sb); -+ file_update_time(vma->vm_file); -+ down_read(&EXT4_I(inode)->i_mmap_sem); -+ size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT; -+ if (vmf->pgoff >= size) -+ ret = VM_FAULT_SIGBUS; -+ up_read(&EXT4_I(inode)->i_mmap_sem); -+ sb_end_pagefault(sb); -+ -+ return ret; - } - - static const struct vm_operations_struct ext4_dax_vm_ops = { - .fault = ext4_dax_fault, - .pmd_fault = ext4_dax_pmd_fault, - .page_mkwrite = ext4_dax_mkwrite, -- .pfn_mkwrite = dax_pfn_mkwrite, -+ .pfn_mkwrite = ext4_dax_pfn_mkwrite, - }; - #else - #define ext4_dax_vm_ops ext4_file_vm_ops - #endif - - static const struct vm_operations_struct ext4_file_vm_ops = { -- .fault = filemap_fault, -+ .fault = ext4_filemap_fault, - .map_pages = filemap_map_pages, - .page_mkwrite = ext4_page_mkwrite, - }; -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index ea433a7f4bca..d1207d03c961 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -3623,6 +3623,15 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) - - } - -+ /* Wait all existing dio workers, newcomers will block on i_mutex */ -+ ext4_inode_block_unlocked_dio(inode); -+ inode_dio_wait(inode); -+ -+ /* -+ * Prevent page faults from reinstantiating pages we have released from -+ * page cache. -+ */ -+ down_write(&EXT4_I(inode)->i_mmap_sem); - first_block_offset = round_up(offset, sb->s_blocksize); - last_block_offset = round_down((offset + length), sb->s_blocksize) - 1; - -@@ -3631,10 +3640,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) - truncate_pagecache_range(inode, first_block_offset, - last_block_offset); - -- /* Wait all existing dio workers, newcomers will block on i_mutex */ -- ext4_inode_block_unlocked_dio(inode); -- inode_dio_wait(inode); -- - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - credits = ext4_writepage_trans_blocks(inode); - else -@@ -3680,16 +3685,12 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) - if (IS_SYNC(inode)) - ext4_handle_sync(handle); - -- /* Now release the pages again to reduce race window */ -- if (last_block_offset > first_block_offset) -- truncate_pagecache_range(inode, first_block_offset, -- last_block_offset); -- - inode->i_mtime = inode->i_ctime = ext4_current_time(inode); - ext4_mark_inode_dirty(handle, inode); - out_stop: - ext4_journal_stop(handle); - out_dio: -+ up_write(&EXT4_I(inode)->i_mmap_sem); - ext4_inode_resume_unlocked_dio(inode); - out_mutex: - mutex_unlock(&inode->i_mutex); -@@ -4823,6 +4824,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) - } else - ext4_wait_for_tail_page_commit(inode); - } -+ down_write(&EXT4_I(inode)->i_mmap_sem); - /* - * Truncate pagecache after we've waited for commit - * in data=journal mode to make pages freeable. -@@ -4830,6 +4832,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) - truncate_pagecache(inode, inode->i_size); - if (shrink) - ext4_truncate(inode); -+ up_write(&EXT4_I(inode)->i_mmap_sem); - } - - if (!rc) { -@@ -5278,6 +5281,8 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) - - sb_start_pagefault(inode->i_sb); - file_update_time(vma->vm_file); -+ -+ down_read(&EXT4_I(inode)->i_mmap_sem); - /* Delalloc case is easy... */ - if (test_opt(inode->i_sb, DELALLOC) && - !ext4_should_journal_data(inode) && -@@ -5347,6 +5352,19 @@ retry_alloc: - out_ret: - ret = block_page_mkwrite_return(ret); - out: -+ up_read(&EXT4_I(inode)->i_mmap_sem); - sb_end_pagefault(inode->i_sb); - return ret; - } -+ -+int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -+{ -+ struct inode *inode = file_inode(vma->vm_file); -+ int err; -+ -+ down_read(&EXT4_I(inode)->i_mmap_sem); -+ err = filemap_fault(vma, vmf); -+ up_read(&EXT4_I(inode)->i_mmap_sem); -+ -+ return err; -+} -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index c9ab67da6e5a..493370e6590e 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -958,6 +958,7 @@ static void init_once(void *foo) - INIT_LIST_HEAD(&ei->i_orphan); - init_rwsem(&ei->xattr_sem); - init_rwsem(&ei->i_data_sem); -+ init_rwsem(&ei->i_mmap_sem); - inode_init_once(&ei->vfs_inode); - } - -diff --git a/fs/ext4/truncate.h b/fs/ext4/truncate.h -index 011ba6670d99..c70d06a383e2 100644 ---- a/fs/ext4/truncate.h -+++ b/fs/ext4/truncate.h -@@ -10,8 +10,10 @@ - */ - static inline void ext4_truncate_failed_write(struct inode *inode) - { -+ down_write(&EXT4_I(inode)->i_mmap_sem); - truncate_inode_pages(inode->i_mapping, inode->i_size); - ext4_truncate(inode); -+ up_write(&EXT4_I(inode)->i_mmap_sem); - } - - /* --- -2.5.5 - diff --git a/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch b/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch deleted file mode 100644 index 9ff9e2761..000000000 --- a/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 011278485ecc3cd2a3954b5d4c73101d919bf1fa Mon Sep 17 00:00:00 2001 -From: Jan Kara <jack@suse.com> -Date: Mon, 7 Dec 2015 14:34:49 -0500 -Subject: [PATCH 4/4] ext4: fix races of writeback with punch hole and zero - range - -When doing delayed allocation, update of on-disk inode size is postponed -until IO submission time. However hole punch or zero range fallocate -calls can end up discarding the tail page cache page and thus on-disk -inode size would never be properly updated. - -Make sure the on-disk inode size is updated before truncating page -cache. - -Signed-off-by: Jan Kara <jack@suse.com> -Signed-off-by: Theodore Ts'o <tytso@mit.edu> ---- - fs/ext4/ext4.h | 3 +++ - fs/ext4/extents.c | 5 +++++ - fs/ext4/inode.c | 35 ++++++++++++++++++++++++++++++++++- - 3 files changed, 42 insertions(+), 1 deletion(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 348a5ff4a0e2..80f76f092079 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -2858,6 +2858,9 @@ static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize) - return changed; - } - -+int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset, -+ loff_t len); -+ - struct ext4_group_info { - unsigned long bb_state; - struct rb_root bb_free_root; -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 4b105c96df08..3578b25fccfd 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4847,6 +4847,11 @@ static long ext4_zero_range(struct file *file, loff_t offset, - * released from page cache. - */ - down_write(&EXT4_I(inode)->i_mmap_sem); -+ ret = ext4_update_disksize_before_punch(inode, offset, len); -+ if (ret) { -+ up_write(&EXT4_I(inode)->i_mmap_sem); -+ goto out_dio; -+ } - /* Now release the pages and zero block aligned part of pages */ - truncate_pagecache_range(inode, start, end - 1); - inode->i_mtime = inode->i_ctime = ext4_current_time(inode); -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index d1207d03c961..472e608da13d 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -3559,6 +3559,35 @@ int ext4_can_truncate(struct inode *inode) - } - - /* -+ * We have to make sure i_disksize gets properly updated before we truncate -+ * page cache due to hole punching or zero range. Otherwise i_disksize update -+ * can get lost as it may have been postponed to submission of writeback but -+ * that will never happen after we truncate page cache. -+ */ -+int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset, -+ loff_t len) -+{ -+ handle_t *handle; -+ loff_t size = i_size_read(inode); -+ -+ WARN_ON(!mutex_is_locked(&inode->i_mutex)); -+ if (offset > size || offset + len < size) -+ return 0; -+ -+ if (EXT4_I(inode)->i_disksize >= size) -+ return 0; -+ -+ handle = ext4_journal_start(inode, EXT4_HT_MISC, 1); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ ext4_update_i_disksize(inode, size); -+ ext4_mark_inode_dirty(handle, inode); -+ ext4_journal_stop(handle); -+ -+ return 0; -+} -+ -+/* - * ext4_punch_hole: punches a hole in a file by releaseing the blocks - * associated with the given offset and length - * -@@ -3636,9 +3665,13 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) - last_block_offset = round_down((offset + length), sb->s_blocksize) - 1; - - /* Now release the pages and zero block aligned part of pages*/ -- if (last_block_offset > first_block_offset) -+ if (last_block_offset > first_block_offset) { -+ ret = ext4_update_disksize_before_punch(inode, offset, length); -+ if (ret) -+ goto out_dio; - truncate_pagecache_range(inode, first_block_offset, - last_block_offset); -+ } - - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - credits = ext4_writepage_trans_blocks(inode); --- -2.5.5 - diff --git a/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch b/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch deleted file mode 100644 index 3bf6765fa..000000000 --- a/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 17048e8a083fec7ad841d88ef0812707fbc7e39f Mon Sep 17 00:00:00 2001 -From: Jan Kara <jack@suse.com> -Date: Mon, 7 Dec 2015 14:29:17 -0500 -Subject: [PATCH 2/4] ext4: move unlocked dio protection from - ext4_alloc_file_blocks() - -Currently ext4_alloc_file_blocks() was handling protection against -unlocked DIO. However we now need to sometimes call it under i_mmap_sem -and sometimes not and DIO protection ranks above it (although strictly -speaking this cannot currently create any deadlocks). Also -ext4_zero_range() was actually getting & releasing unlocked DIO -protection twice in some cases. Luckily it didn't introduce any real bug -but it was a land mine waiting to be stepped on. So move DIO protection -out from ext4_alloc_file_blocks() into the two callsites. - -Signed-off-by: Jan Kara <jack@suse.com> -Signed-off-by: Theodore Ts'o <tytso@mit.edu> ---- - fs/ext4/extents.c | 21 ++++++++++----------- - 1 file changed, 10 insertions(+), 11 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 5be9ca5a8a7a..65b5ada2833f 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4685,10 +4685,6 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset, - if (len <= EXT_UNWRITTEN_MAX_LEN) - flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; - -- /* Wait all existing dio workers, newcomers will block on i_mutex */ -- ext4_inode_block_unlocked_dio(inode); -- inode_dio_wait(inode); -- - /* - * credits to insert 1 extent into extent tree - */ -@@ -4752,8 +4748,6 @@ retry: - goto retry; - } - -- ext4_inode_resume_unlocked_dio(inode); -- - return ret > 0 ? ret2 : ret; - } - -@@ -4827,6 +4821,10 @@ static long ext4_zero_range(struct file *file, loff_t offset, - if (mode & FALLOC_FL_KEEP_SIZE) - flags |= EXT4_GET_BLOCKS_KEEP_SIZE; - -+ /* Wait all existing dio workers, newcomers will block on i_mutex */ -+ ext4_inode_block_unlocked_dio(inode); -+ inode_dio_wait(inode); -+ - /* Preallocate the range including the unaligned edges */ - if (partial_begin || partial_end) { - ret = ext4_alloc_file_blocks(file, -@@ -4835,7 +4833,7 @@ static long ext4_zero_range(struct file *file, loff_t offset, - round_down(offset, 1 << blkbits)) >> blkbits, - new_size, flags, mode); - if (ret) -- goto out_mutex; -+ goto out_dio; - - } - -@@ -4844,10 +4842,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, - flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | - EXT4_EX_NOCACHE); - -- /* Wait all existing dio workers, newcomers will block on i_mutex */ -- ext4_inode_block_unlocked_dio(inode); -- inode_dio_wait(inode); -- - /* - * Prevent page faults from reinstantiating pages we have - * released from page cache. -@@ -4992,8 +4986,13 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) - goto out; - } - -+ /* Wait all existing dio workers, newcomers will block on i_mutex */ -+ ext4_inode_block_unlocked_dio(inode); -+ inode_dio_wait(inode); -+ - ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, - flags, mode); -+ ext4_inode_resume_unlocked_dio(inode); - if (ret) - goto out; - --- -2.5.5 - diff --git a/input-gtco-fix-crash-on-detecting-device-without-end.patch b/input-gtco-fix-crash-on-detecting-device-without-end.patch deleted file mode 100644 index 849f607a5..000000000 --- a/input-gtco-fix-crash-on-detecting-device-without-end.patch +++ /dev/null @@ -1,49 +0,0 @@ -Subject: [PATCH] Input: gtco: fix crash on detecting device without endpoints -From: Vladis Dronov <vdronov@redhat.com> -Date: 2016-03-18 18:35:00 - -The gtco driver expects at least one valid endpoint. If given -malicious descriptors that specify 0 for the number of endpoints, -it will crash in the probe function. Ensure there is at least -one endpoint on the interface before using it. Fix minor coding -style issue. - -The full report of this issue can be found here: -http://seclists.org/bugtraq/2016/Mar/86 - -Reported-by: Ralf Spenneberg <ralf@spenneberg.net> -Signed-off-by: Vladis Dronov <vdronov@redhat.com> ---- - drivers/input/tablet/gtco.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c -index 3a7f3a4..7c18249 100644 ---- a/drivers/input/tablet/gtco.c -+++ b/drivers/input/tablet/gtco.c -@@ -858,6 +858,14 @@ static int gtco_probe(struct usb_interface *usbinterface, - goto err_free_buf; - } - -+ /* Sanity check that a device has an endpoint */ -+ if (usbinterface->altsetting[0].desc.bNumEndpoints < 1) { -+ dev_err(&usbinterface->dev, -+ "Invalid number of endpoints\n"); -+ error = -EINVAL; -+ goto err_free_urb; -+ } -+ - /* - * The endpoint is always altsetting 0, we know this since we know - * this device only has one interrupt endpoint -@@ -879,7 +887,7 @@ static int gtco_probe(struct usb_interface *usbinterface, - * HID report descriptor - */ - if (usb_get_extra_descriptor(usbinterface->cur_altsetting, -- HID_DEVICE_TYPE, &hid_desc) != 0){ -+ HID_DEVICE_TYPE, &hid_desc) != 0) { - dev_err(&usbinterface->dev, - "Can't retrieve exta USB descriptor to get hid report descriptor length\n"); - error = -EIO; --- -2.5.0 diff --git a/kernel.spec b/kernel.spec index f2b313d44..4134f18c9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -58,7 +58,7 @@ Summary: The Linux kernel %define stable_rc 0 # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -645,30 +645,15 @@ Patch664: netfilter-x_tables-check-for-size-overflow.patch #CVE-2016-3134 rhbz 1317383 1317384 Patch665: netfilter-x_tables-deal-with-bogus-nextoffset-values.patch -#CVE-2016-2187 rhbz 1317017 1317010 -Patch686: input-gtco-fix-crash-on-detecting-device-without-end.patch - # CVE-2016-3672 rhbz 1324749 1324750 Patch690: x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch -#CVE-2015-8839 rhbz 1323577 1323579 -Patch691: ext4-fix-races-between-page-faults-and-hole-punching.patch -Patch692: ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch -Patch693: ext4-fix-races-between-buffered-IO-and-collapse-inse.patch -Patch694: ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch - #CVE-2016-3951 rhbz 1324782 1324815 Patch695: cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch #rhbz 1309980 Patch698: 0001-ACPI-processor-Request-native-thermal-interrupt-hand.patch -# CVE-2016-3961 rhbz 1327219 1323956 -Patch699: x86-xen-suppress-hugetlbfs-in-PV-guests.patch - -# CVE-2016-3955 rhbz 1328478 1328479 -Patch700: USB-usbip-fix-potential-out-of-bounds-write.patch - #rhbz 1309487 Patch701: antenna_select.patch @@ -681,6 +666,13 @@ Patch704: x86-efi-bgrt-Switch-all-pr_err-to-pr_debug-for-inval.patch #CVE-2016-4482 rhbz 1332931 1332932 Patch705: USB-usbfs-fix-potential-infoleak-in-devio.patch +#CVE-2016-4486 CVE-2016-4485 rhbz 1333316 1333309 1333321 +Patch706: net-fix-infoleak-in-llc.patch +Patch707: net-fix-infoleak-in-rtnetlink.patch + +#CVE-2016-xxxx rhbz 1333712 1333713 +Patch708: propogate_mnt-Handle-the-first-propogated-copy-being.patch + # END OF PATCH DEFINITIONS %endif @@ -1374,30 +1366,15 @@ ApplyPatch netfilter-x_tables-check-for-size-overflow.patch #CVE-2016-3134 rhbz 1317383 1317384 ApplyPatch netfilter-x_tables-deal-with-bogus-nextoffset-values.patch -#CVE-2016-2187 rhbz 1317017 1317010 -ApplyPatch input-gtco-fix-crash-on-detecting-device-without-end.patch - # CVE-2016-3672 rhbz 1324749 1324750 ApplyPatch x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch -#CVE-2015-8839 rhbz 1323577 1323579 -ApplyPatch ext4-fix-races-between-page-faults-and-hole-punching.patch -ApplyPatch ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch -ApplyPatch ext4-fix-races-between-buffered-IO-and-collapse-inse.patch -ApplyPatch ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch - #CVE-2016-3951 rhbz 1324782 1324815 ApplyPatch cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch #rhbz 1309980 ApplyPatch 0001-ACPI-processor-Request-native-thermal-interrupt-hand.patch -# CVE-2016-3961 rhbz 1327219 1323956 -ApplyPatch x86-xen-suppress-hugetlbfs-in-PV-guests.patch - -# CVE-2016-3955 rhbz 1328478 1328479 -ApplyPatch USB-usbip-fix-potential-out-of-bounds-write.patch - #rhbz 1309487 ApplyPatch antenna_select.patch @@ -1407,6 +1384,13 @@ ApplyPatch ipv4-fib-don-t-warn-when-primary-address-is-missing-.patch #CVE-2016-4482 rhbz 1332931 1332932 ApplyPatch USB-usbfs-fix-potential-infoleak-in-devio.patch +#CVE-2016-4486 CVE-2016-4485 rhbz 1333316 1333309 1333321 +ApplyPatch net-fix-infoleak-in-llc.patch +ApplyPatch net-fix-infoleak-in-rtnetlink.patch + +#CVE-2016-xxxx rhbz 1333712 1333713 +ApplyPatch propogate_mnt-Handle-the-first-propogated-copy-being.patch + # END OF PATCH APPLICATIONS %endif @@ -2256,6 +2240,15 @@ fi # # %changelog +* Fri May 06 2016 Laura Abbott <labbott@fedoraproject.org> - 4.4.9-200 +- Linux v4.4.9 + +* Fri May 06 2016 Josh Boyer <jwboyer@fedoraproject.org> +- Oops in propogate_mnt if first copy is slave (rhbz 1333712 1333713) + +* Thu May 05 2016 Josh Boyer <jwboyer@fedoraproject.org> +- CVE-2016-4486 CVE-2016-4485 info leaks (rhbz 1333316 1333309 1333321) + * Wed May 04 2016 Josh Boyer <jwboyer@fedoraproject.org> - CVE-2016-4482 info leak in devio.c (rhbz 1332931 1332932) diff --git a/net-fix-infoleak-in-llc.patch b/net-fix-infoleak-in-llc.patch new file mode 100644 index 000000000..38f0d506a --- /dev/null +++ b/net-fix-infoleak-in-llc.patch @@ -0,0 +1,32 @@ +From ec0de35ded8c4a8588290a1b442aa3aa4bdf4de1 Mon Sep 17 00:00:00 2001 +From: Kangjie Lu <kangjielu@gmail.com> +Date: Tue, 3 May 2016 16:35:05 -0400 +Subject: [PATCH 2/2] net: fix infoleak in llc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The stack object “info” has a total size of 12 bytes. Its last byte +is padding which is not initialized and leaked via “put_cmsg”. + +Signed-off-by: Kangjie Lu <kjlu@gatech.edu> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + net/llc/af_llc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index b3c52e3f689a..8ae3ed97d95c 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -626,6 +626,7 @@ static void llc_cmsg_rcv(struct msghdr *msg, struct sk_buff *skb) + if (llc->cmsg_flags & LLC_CMSG_PKTINFO) { + struct llc_pktinfo info; + ++ memset(&info, 0, sizeof(info)); + info.lpi_ifindex = llc_sk(skb->sk)->dev->ifindex; + llc_pdu_decode_dsap(skb, &info.lpi_sap); + llc_pdu_decode_da(skb, info.lpi_mac); +-- +2.5.5 + diff --git a/net-fix-infoleak-in-rtnetlink.patch b/net-fix-infoleak-in-rtnetlink.patch new file mode 100644 index 000000000..0da35108d --- /dev/null +++ b/net-fix-infoleak-in-rtnetlink.patch @@ -0,0 +1,50 @@ +From 55a8a812d867ec9953bde7d86eef255a1abbf93e Mon Sep 17 00:00:00 2001 +From: Kangjie Lu <kangjielu@gmail.com> +Date: Tue, 3 May 2016 16:46:24 -0400 +Subject: [PATCH 1/2] net: fix infoleak in rtnetlink +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The stack object “map” has a total size of 32 bytes. Its last 4 +bytes are padding generated by compiler. These padding bytes are +not initialized and sent out via “nla_put”. + +Signed-off-by: Kangjie Lu <kjlu@gatech.edu> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + net/core/rtnetlink.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index a75f7e94b445..65763c29f845 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1180,14 +1180,16 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, + + static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev) + { +- struct rtnl_link_ifmap map = { +- .mem_start = dev->mem_start, +- .mem_end = dev->mem_end, +- .base_addr = dev->base_addr, +- .irq = dev->irq, +- .dma = dev->dma, +- .port = dev->if_port, +- }; ++ struct rtnl_link_ifmap map; ++ ++ memset(&map, 0, sizeof(map)); ++ map.mem_start = dev->mem_start; ++ map.mem_end = dev->mem_end; ++ map.base_addr = dev->base_addr; ++ map.irq = dev->irq; ++ map.dma = dev->dma; ++ map.port = dev->if_port; ++ + if (nla_put(skb, IFLA_MAP, sizeof(map), &map)) + return -EMSGSIZE; + +-- +2.5.5 + diff --git a/propogate_mnt-Handle-the-first-propogated-copy-being.patch b/propogate_mnt-Handle-the-first-propogated-copy-being.patch new file mode 100644 index 000000000..b3ae53c5a --- /dev/null +++ b/propogate_mnt-Handle-the-first-propogated-copy-being.patch @@ -0,0 +1,146 @@ +From 27844237d77df76c816034a78178b23c070eef88 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" <ebiederm@xmission.com> +Date: Thu, 5 May 2016 09:29:29 -0500 +Subject: [PATCH] propogate_mnt: Handle the first propogated copy being a slave + +When the first propgated copy was a slave the following oops would result: +> BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 +> IP: [<ffffffff811fba4e>] propagate_one+0xbe/0x1c0 +> PGD bacd4067 PUD bac66067 PMD 0 +> Oops: 0000 [#1] SMP +> Modules linked in: +> CPU: 1 PID: 824 Comm: mount Not tainted 4.6.0-rc5userns+ #1523 +> Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 +> task: ffff8800bb0a8000 ti: ffff8800bac3c000 task.ti: ffff8800bac3c000 +> RIP: 0010:[<ffffffff811fba4e>] [<ffffffff811fba4e>] propagate_one+0xbe/0x1c0 +> RSP: 0018:ffff8800bac3fd38 EFLAGS: 00010283 +> RAX: 0000000000000000 RBX: ffff8800bb77ec00 RCX: 0000000000000010 +> RDX: 0000000000000000 RSI: ffff8800bb58c000 RDI: ffff8800bb58c480 +> RBP: ffff8800bac3fd48 R08: 0000000000000001 R09: 0000000000000000 +> R10: 0000000000001ca1 R11: 0000000000001c9d R12: 0000000000000000 +> R13: ffff8800ba713800 R14: ffff8800bac3fda0 R15: ffff8800bb77ec00 +> FS: 00007f3c0cd9b7e0(0000) GS:ffff8800bfb00000(0000) knlGS:0000000000000000 +> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +> CR2: 0000000000000010 CR3: 00000000bb79d000 CR4: 00000000000006e0 +> Stack: +> ffff8800bb77ec00 0000000000000000 ffff8800bac3fd88 ffffffff811fbf85 +> ffff8800bac3fd98 ffff8800bb77f080 ffff8800ba713800 ffff8800bb262b40 +> 0000000000000000 0000000000000000 ffff8800bac3fdd8 ffffffff811f1da0 +> Call Trace: +> [<ffffffff811fbf85>] propagate_mnt+0x105/0x140 +> [<ffffffff811f1da0>] attach_recursive_mnt+0x120/0x1e0 +> [<ffffffff811f1ec3>] graft_tree+0x63/0x70 +> [<ffffffff811f1f6b>] do_add_mount+0x9b/0x100 +> [<ffffffff811f2c1a>] do_mount+0x2aa/0xdf0 +> [<ffffffff8117efbe>] ? strndup_user+0x4e/0x70 +> [<ffffffff811f3a45>] SyS_mount+0x75/0xc0 +> [<ffffffff8100242b>] do_syscall_64+0x4b/0xa0 +> [<ffffffff81988f3c>] entry_SYSCALL64_slow_path+0x25/0x25 +> Code: 00 00 75 ec 48 89 0d 02 22 22 01 8b 89 10 01 00 00 48 89 05 fd 21 22 01 39 8e 10 01 00 00 0f 84 e0 00 00 00 48 8b 80 d8 00 00 00 <48> 8b 50 10 48 89 05 df 21 22 01 48 89 15 d0 21 22 01 8b 53 30 +> RIP [<ffffffff811fba4e>] propagate_one+0xbe/0x1c0 +> RSP <ffff8800bac3fd38> +> CR2: 0000000000000010 +> ---[ end trace 2725ecd95164f217 ]--- + +This oops happens with the namespace_sem held and can be triggered by +non-root users. An all around not pleasant experience. + +To avoid this scenario when finding the appropriate source mount to +copy stop the walk up the mnt_master chain when the first source mount +is encountered. + +Further rewrite the walk up the last_source mnt_master chain so that +it is clear what is going on. + +The reason why the first source mount is special is that it it's +mnt_parent is not a mount in the dest_mnt propagation tree, and as +such termination conditions based up on the dest_mnt mount propgation +tree do not make sense. + +To avoid other kinds of confusion last_dest is not changed when +computing last_source. last_dest is only used once in propagate_one +and that is above the point of the code being modified, so changing +the global variable is meaningless and confusing. + +Cc: stable@vger.kernel.org +fixes: f2ebb3a921c1ca1e2ddd9242e95a1989a50c4c68 ("smarter propagate_mnt()") +Reported-by: Tycho Andersen <tycho.andersen@canonical.com> +Reviewed-by: Seth Forshee <seth.forshee@canonical.com> +Tested-by: Seth Forshee <seth.forshee@canonical.com> +Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> + +Backported-by: Josh Boyer <jwboyer@fedoraproject.org> +--- + fs/pnode.c | 32 ++++++++++++++++++++------------ + 1 file changed, 20 insertions(+), 12 deletions(-) + +diff --git a/fs/pnode.c b/fs/pnode.c +index 6367e1e435c6..e7705149d430 100644 +--- a/fs/pnode.c ++++ b/fs/pnode.c +@@ -198,10 +198,15 @@ static struct mount *next_group(struct mount *m, struct mount *origin) + + /* all accesses are serialized by namespace_sem */ + static struct user_namespace *user_ns; +-static struct mount *last_dest, *last_source, *dest_master; ++static struct mount *last_dest, *first_source, *last_source, *dest_master; + static struct mountpoint *mp; + static struct hlist_head *list; + ++static inline bool peers(struct mount *m1, struct mount *m2) ++{ ++ return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id; ++} ++ + static int propagate_one(struct mount *m) + { + struct mount *child; +@@ -212,24 +217,26 @@ static int propagate_one(struct mount *m) + /* skip if mountpoint isn't covered by it */ + if (!is_subdir(mp->m_dentry, m->mnt.mnt_root)) + return 0; +- if (m->mnt_group_id == last_dest->mnt_group_id) { ++ if (peers(m,last_dest)) { + type = CL_MAKE_SHARED; + } else { + struct mount *n, *p; ++ bool done; + for (n = m; ; n = p) { + p = n->mnt_master; +- if (p == dest_master || IS_MNT_MARKED(p)) { +- while (last_dest->mnt_master != p) { +- last_source = last_source->mnt_master; +- last_dest = last_source->mnt_parent; +- } +- if (n->mnt_group_id != last_dest->mnt_group_id) { +- last_source = last_source->mnt_master; +- last_dest = last_source->mnt_parent; +- } ++ if (p == dest_master || IS_MNT_MARKED(p)) + break; +- } + } ++ do { ++ struct mount *parent = last_source->mnt_parent; ++ if (last_source == first_source) ++ break; ++ done = parent->mnt_master == p; ++ if (done && peers(n, parent)) ++ break; ++ last_source = last_source->mnt_master; ++ } while (!done); ++ + type = CL_SLAVE; + /* beginning of peer group among the slaves? */ + if (IS_MNT_SHARED(m)) +@@ -281,6 +288,7 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, + */ + user_ns = current->nsproxy->mnt_ns->user_ns; + last_dest = dest_mnt; ++ first_source = source_mnt; + last_source = source_mnt; + mp = dest_mp; + list = tree_list; +-- +2.5.5 + @@ -1,3 +1,3 @@ 9a78fa2eb6c68ca5a40ed5af08142599 linux-4.4.tar.xz dcbc8fe378a676d5d0dd208cf524e144 perf-man-4.4.tar.gz -c1d8f46e5b2ee7c925fc38f20a3726d3 patch-4.4.8.xz +b0c445b438e7563f2e33dba9edc926eb patch-4.4.9.xz diff --git a/x86-xen-suppress-hugetlbfs-in-PV-guests.patch b/x86-xen-suppress-hugetlbfs-in-PV-guests.patch deleted file mode 100644 index 1b7c8f24a..000000000 --- a/x86-xen-suppress-hugetlbfs-in-PV-guests.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 72c339e0c6d9969e664c2cf63e162753d7d859ae Mon Sep 17 00:00:00 2001 -From: Jan Beulich <jbeulich@suse.com> -Date: Thu, 14 Apr 2016 13:03:47 +0000 -Subject: [PATCH] x86/xen: suppress hugetlbfs in PV guests - -Huge pages are not normally available to PV guests. Not suppressing -hugetlbfs use results in an endless loop of page faults when user mode -code tries to access a hugetlbfs mapped area (since the hypervisor -denies such PTEs to be created, but error indications can't be -propagated out of xen_set_pte_at(), just like for various of its -siblings), and - once killed in an oops like this: - -kernel BUG at .../fs/hugetlbfs/inode.c:428! -invalid opcode: 0000 [#1] SMP -Modules linked in: ... -Supported: Yes -CPU: 2 PID: 6088 Comm: hugetlbfs Tainted: G W 4.4.0-2016-01-20-pv #2 -Hardware name: ... -task: ffff8808059205c0 ti: ffff880803c84000 task.ti: ffff880803c84000 -RIP: e030:[<ffffffff811c333b>] [<ffffffff811c333b>] remove_inode_hugepages+0x25b/0x320 -RSP: e02b:ffff880803c879a8 EFLAGS: 00010202 -RAX: 000000000077a4db RBX: ffffea001acff000 RCX: 0000000078417d38 -RDX: 0000000000000000 RSI: 000000007e154fa7 RDI: ffff880805d70960 -RBP: 0000000000000960 R08: 0000000000000000 R09: 0000000000000000 -R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000 -R13: ffff880807486018 R14: 0000000000000000 R15: ffff880803c87af0 -FS: 00007f85fa8b8700(0000) GS:ffff88080b640000(0000) knlGS:0000000000000000 -CS: e033 DS: 0000 ES: 0000 CR0: 000000008005003b -CR2: 00007f85fa000000 CR3: 0000000001a0a000 CR4: 0000000000040660 -Stack: - ffff880000000fb0 ffff880803c87a18 ffff880803c87ae8 ffff8808059205c0 - ffff880803c87af0 ffff880803c87ae8 ffff880807486018 0000000000000000 - ffffffff81bf6e60 ffff880807486168 000003ffffffffff 0000000003c87758 -Call Trace: - [<ffffffff811c3415>] hugetlbfs_evict_inode+0x15/0x40 - [<ffffffff81167b3d>] evict+0xbd/0x1b0 - [<ffffffff8116514a>] __dentry_kill+0x19a/0x1f0 - [<ffffffff81165b0e>] dput+0x1fe/0x220 - [<ffffffff81150535>] __fput+0x155/0x200 - [<ffffffff81079fc0>] task_work_run+0x60/0xa0 - [<ffffffff81063510>] do_exit+0x160/0x400 - [<ffffffff810637eb>] do_group_exit+0x3b/0xa0 - [<ffffffff8106e8bd>] get_signal+0x1ed/0x470 - [<ffffffff8100f854>] do_signal+0x14/0x110 - [<ffffffff810030e9>] prepare_exit_to_usermode+0xe9/0xf0 - [<ffffffff814178a5>] retint_user+0x8/0x13 - -This is XSA-174. - -Signed-off-by: Jan Beulich <jbeulich@suse.com> -Cc: stable@vger.kernel.org ---- - arch/x86/include/asm/hugetlb.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h -index f8a29d2c97b0..e6a8613fbfb0 100644 ---- a/arch/x86/include/asm/hugetlb.h -+++ b/arch/x86/include/asm/hugetlb.h -@@ -4,6 +4,7 @@ - #include <asm/page.h> - #include <asm-generic/hugetlb.h> - -+#define hugepages_supported() cpu_has_pse - - static inline int is_hugepage_only_range(struct mm_struct *mm, - unsigned long addr, --- -2.5.5 - |