From bca16600c0a6e7fa6ebc3abd076c06d54d34c1dc Mon Sep 17 00:00:00 2001 From: Andreas Wellving Date: Mon, 22 Oct 2018 16:17:43 +0200 Subject: Modify CVE-2018-5390, CVE-2018-10876 and CVE-2018-10879 Correct CVE-2018-5390 according to kernel version, remove CVE-2018-10876 and CVE-2018-10879. CVE-2018-5390 References: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.9.y&id=2d08921c8da26bdce3d8848ef6f32068f594d7d4 Change-Id: I83d497af94f3e521cece3ab7d19a20e5d0157421 Signed-off-by: Andreas Wellving --- patches/cve/4.9.x.scc | 2 - ...look-at-the-bg_flags-field-if-it-is-valid.patch | 135 ----------------- ...ure-bitmaps-and-the-inode-table-don-t-ove.patch | 83 ----------- ...batches-of-packets-in-tcp_prune_ofo_queue.patch | 163 +++++---------------- 4 files changed, 39 insertions(+), 344 deletions(-) delete mode 100644 patches/cve/CVE-2018-10876-ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch delete mode 100644 patches/cve/CVE-2018-10879-ext4-make-sure-bitmaps-and-the-inode-table-don-t-ove.patch diff --git a/patches/cve/4.9.x.scc b/patches/cve/4.9.x.scc index 5fe1ee7..cf11548 100644 --- a/patches/cve/4.9.x.scc +++ b/patches/cve/4.9.x.scc @@ -27,10 +27,8 @@ patch CVE-2017-18255-perf-core-Fix-the-perf_cpu_time_max_percent-check.patch patch CVE-2018-9518-NFC-llcp-Limit-size-of-SDP-URI.patch #CVEs fixed in 4.9.112: -patch CVE-2018-10876-ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch patch CVE-2018-10877-ext4-verify-the-depth-of-extent-tree-in-ext4_find_ex.patch patch CVE-2018-10878-ext4-always-check-block-group-bounds-in-ext4_init_bl.patch -patch CVE-2018-10879-ext4-make-sure-bitmaps-and-the-inode-table-don-t-ove.patch patch CVE-2018-10881-ext4-clear-i_data-in-ext4_inode_info-when-removing-i.patch patch CVE-2018-10882-ext4-add-more-inode-number-paranoia-checks.patch patch CVE-2018-9516-HID-debug-check-length-before-copy_to_user.patch diff --git a/patches/cve/CVE-2018-10876-ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch b/patches/cve/CVE-2018-10876-ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch deleted file mode 100644 index fe172e6..0000000 --- a/patches/cve/CVE-2018-10876-ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch +++ /dev/null @@ -1,135 +0,0 @@ -Date: Fri, 12 Oct 2018 13:56:16 +0200 -Subject: [PATCH] ext4: only look at the bg_flags field if it is valid The - bg_flags field in the block group descripts is only valid if the uninit_bg or - metadata_csum feature is enabled. We were not consistently looking at this - field; fix this. - -Also block group #0 must never have uninitialized allocation bitmaps, -or need to be zeroed, since that's where the root inode, and other -special inodes are set up. Check for these conditions and mark the -file system as corrupted if they are detected. - -This addresses CVE-2018-10876. -Upstream-Status: Backport - -https://bugzilla.kernel.org/show_bug.cgi?id=199403 - -Signed-off-by: Theodore Ts'o -Cc: stable@kernel.org -Signed-off-by: Andreas Wellving ---- - fs/ext4/balloc.c | 11 ++++++++++- - fs/ext4/ialloc.c | 14 ++++++++++++-- - fs/ext4/mballoc.c | 6 ++++-- - fs/ext4/super.c | 11 ++++++++++- - 4 files changed, 36 insertions(+), 6 deletions(-) - -diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c -index e04ec86..10e18f7 100644 ---- a/fs/ext4/balloc.c -+++ b/fs/ext4/balloc.c -@@ -443,7 +443,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) - goto verify; - } - ext4_lock_group(sb, block_group); -- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { -+ if (ext4_has_group_desc_csum(sb) && -+ (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { -+ if (block_group == 0) { -+ ext4_unlock_group(sb, block_group); -+ unlock_buffer(bh); -+ ext4_error(sb, "Block bitmap for bg 0 marked " -+ "uninitialized"); -+ err = -EFSCORRUPTED; -+ goto out; -+ } - err = ext4_init_block_bitmap(sb, bh, block_group, desc); - set_bitmap_uptodate(bh); - set_buffer_uptodate(bh); -diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c -index 2d94e85..e937aad 100644 ---- a/fs/ext4/ialloc.c -+++ b/fs/ext4/ialloc.c -@@ -183,7 +183,16 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) - } - - ext4_lock_group(sb, block_group); -- if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { -+ if (ext4_has_group_desc_csum(sb) && -+ (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) { -+ if (block_group == 0) { -+ ext4_unlock_group(sb, block_group); -+ unlock_buffer(bh); -+ ext4_error(sb, "Inode bitmap for bg 0 marked " -+ "uninitialized"); -+ err = -EFSCORRUPTED; -+ goto out; -+ } - err = ext4_init_inode_bitmap(sb, bh, block_group, desc); - set_bitmap_uptodate(bh); - set_buffer_uptodate(bh); -@@ -960,7 +969,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, - - /* recheck and clear flag under lock if we still need to */ - ext4_lock_group(sb, group); -- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { -+ if (ext4_has_group_desc_csum(sb) && -+ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { - gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); - ext4_free_group_clusters_set(sb, gdp, - ext4_free_clusters_after_init(sb, group, gdp)); -diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c -index 64056c6..4869946 100644 ---- a/fs/ext4/mballoc.c -+++ b/fs/ext4/mballoc.c -@@ -2444,7 +2444,8 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, - * initialize bb_free to be able to skip - * empty groups without initialization - */ -- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { -+ if (ext4_has_group_desc_csum(sb) && -+ (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { - meta_group_info[i]->bb_free = - ext4_free_clusters_after_init(sb, group, desc); - } else { -@@ -2969,7 +2970,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, - #endif - ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start, - ac->ac_b_ex.fe_len); -- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { -+ if (ext4_has_group_desc_csum(sb) && -+ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { - gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); - ext4_free_group_clusters_set(sb, gdp, - ext4_free_clusters_after_init(sb, -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 1f58179..97d322b 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -2991,13 +2991,22 @@ static ext4_group_t ext4_has_uninit_itable(struct super_block *sb) - ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; - struct ext4_group_desc *gdp = NULL; - -+ if (!ext4_has_group_desc_csum(sb)) -+ return ngroups; -+ - for (group = 0; group < ngroups; group++) { - gdp = ext4_get_group_desc(sb, group, NULL); - if (!gdp) - continue; - -- if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) -+ if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)) -+ continue; -+ if (group != 0) - break; -+ ext4_error(sb, "Inode table for bg 0 marked as " -+ "needing zeroing"); -+ if (sb_rdonly(sb)) -+ return ngroups; - } - - return group; --- - - diff --git a/patches/cve/CVE-2018-10879-ext4-make-sure-bitmaps-and-the-inode-table-don-t-ove.patch b/patches/cve/CVE-2018-10879-ext4-make-sure-bitmaps-and-the-inode-table-don-t-ove.patch deleted file mode 100644 index 439c9e9..0000000 --- a/patches/cve/CVE-2018-10879-ext4-make-sure-bitmaps-and-the-inode-table-don-t-ove.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 77260807d1170a8cf35dbb06e07461a655f67eee Mon Sep 17 00:00:00 2001 -From: Theodore Ts'o -Date: Wed, 13 Jun 2018 23:08:26 -0400 -Subject: [PATCH] ext4: make sure bitmaps and the inode table don't overlap - with bg descriptors - -It's really bad when the allocation bitmaps and the inode table -overlap with the block group descriptors, since it causes random -corruption of the bg descriptors. So we really want to head those off -at the pass. - -https://bugzilla.kernel.org/show_bug.cgi?id=199865 - -CVE: CVE-2018-10879 -Upstream-Status: Backport - -Signed-off-by: Theodore Ts'o -Cc: stable@kernel.org -Signed-off-by: Andreas Wellving ---- - fs/ext4/super.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index c8b7b83..c61675d 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -2348,6 +2348,7 @@ static int ext4_check_descriptors(struct super_block *sb, - struct ext4_sb_info *sbi = EXT4_SB(sb); - ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); - ext4_fsblk_t last_block; -+ ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1; - ext4_fsblk_t block_bitmap; - ext4_fsblk_t inode_bitmap; - ext4_fsblk_t inode_table; -@@ -2380,6 +2381,14 @@ static int ext4_check_descriptors(struct super_block *sb, - if (!sb_rdonly(sb)) - return 0; - } -+ if (block_bitmap >= sb_block + 1 && -+ block_bitmap <= last_bg_block) { -+ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " -+ "Block bitmap for group %u overlaps " -+ "block group descriptors", i); -+ if (!sb_rdonly(sb)) -+ return 0; -+ } - if (block_bitmap < first_block || block_bitmap > last_block) { - ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " - "Block bitmap for group %u not in group " -@@ -2394,6 +2403,14 @@ static int ext4_check_descriptors(struct super_block *sb, - if (!sb_rdonly(sb)) - return 0; - } -+ if (inode_bitmap >= sb_block + 1 && -+ inode_bitmap <= last_bg_block) { -+ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " -+ "Inode bitmap for group %u overlaps " -+ "block group descriptors", i); -+ if (!sb_rdonly(sb)) -+ return 0; -+ } - if (inode_bitmap < first_block || inode_bitmap > last_block) { - ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " - "Inode bitmap for group %u not in group " -@@ -2408,6 +2425,14 @@ static int ext4_check_descriptors(struct super_block *sb, - if (!sb_rdonly(sb)) - return 0; - } -+ if (inode_table >= sb_block + 1 && -+ inode_table <= last_bg_block) { -+ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " -+ "Inode table for group %u overlaps " -+ "block group descriptors", i); -+ if (!sb_rdonly(sb)) -+ return 0; -+ } - if (inode_table < first_block || - inode_table + sbi->s_itb_per_group - 1 > last_block) { - ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " --- -2.7.4 - diff --git a/patches/cve/CVE-2018-5390-tcp-free-batches-of-packets-in-tcp_prune_ofo_queue.patch b/patches/cve/CVE-2018-5390-tcp-free-batches-of-packets-in-tcp_prune_ofo_queue.patch index b8f95d0..35d1eec 100644 --- a/patches/cve/CVE-2018-5390-tcp-free-batches-of-packets-in-tcp_prune_ofo_queue.patch +++ b/patches/cve/CVE-2018-5390-tcp-free-batches-of-packets-in-tcp_prune_ofo_queue.patch @@ -1,134 +1,60 @@ -Date: Mon, 15 Oct 2018 06:07:41 +0200 -Subject: [PATCH] Merge branch 'tcp-robust-ooo' +From 2d08921c8da26bdce3d8848ef6f32068f594d7d4 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 23 Jul 2018 09:28:17 -0700 +Subject: [PATCH] tcp: free batches of packets in tcp_prune_ofo_queue() -Eric Dumazet says: +[ Upstream commit 72cd43ba64fc172a443410ce01645895850844c8 ] -==================== Juha-Matti Tilli reported that malicious peers could inject tiny packets in out_of_order_queue, forcing very expensive calls to tcp_collapse_ofo_queue() and tcp_prune_ofo_queue() for -every incoming packet. +every incoming packet. out_of_order_queue rb-tree can contain +thousands of nodes, iterating over all of them is not nice. -With tcp_rmem[2] default of 6MB, the ooo queue could -contain ~7000 nodes. +Before linux-4.9, we would have pruned all packets in ofo_queue +in one go, every XXXX packets. XXXX depends on sk_rcvbuf and skbs +truesize, but is about 7000 packets with tcp_rmem[2] default of 6 MB. -This patch series makes sure we cut cpu cycles enough to -render the attack not critical. +Since we plan to increase tcp_rmem[2] in the future to cope with +modern BDP, can not revert to the old behavior, without great pain. -We might in the future go further, like disconnecting -or black-holing proven malicious flows. -==================== +Strategy taken in this patch is to purge ~12.5 % of the queue capacity. + +Fixes: 36a6503fedda ("tcp: refine tcp_prune_ofo_queue() to not drop all packets") CVE: CVE-2018-5390 Upstream-Status: Backport +Signed-off-by: Eric Dumazet +Reported-by: Juha-Matti Tilli +Acked-by: Yuchung Cheng +Acked-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andreas Wellving --- - net/ipv4/tcp_input.c | 60 +++++++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 50 insertions(+), 10 deletions(-) + include/linux/skbuff.h | 2 ++ + net/ipv4/tcp_input.c | 15 +++++++++++---- + 2 files changed, 13 insertions(+), 4 deletions(-) -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 2f107e4..4838b5f 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -4355,6 +4355,23 @@ static bool tcp_try_coalesce(struct sock *sk, - return true; +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index b048d3d..1f207dd 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2982,6 +2982,8 @@ static inline int __skb_grow_rcsum(struct sk_buff *skb, unsigned int len) + return __skb_grow(skb, len); } -+static bool tcp_ooo_try_coalesce(struct sock *sk, -+ struct sk_buff *to, -+ struct sk_buff *from, -+ bool *fragstolen) -+{ -+ bool res = tcp_try_coalesce(sk, to, from, fragstolen); ++#define rb_to_skb(rb) rb_entry_safe(rb, struct sk_buff, rbnode) + -+ /* In case tcp_drop() is called later, update to->gso_segs */ -+ if (res) { -+ u32 gso_segs = max_t(u16, 1, skb_shinfo(to)->gso_segs) + -+ max_t(u16, 1, skb_shinfo(from)->gso_segs); -+ -+ skb_shinfo(to)->gso_segs = min_t(u32, gso_segs, 0xFFFF); -+ } -+ return res; -+} -+ - static void tcp_drop(struct sock *sk, struct sk_buff *skb) - { - sk_drops_add(sk, skb); -@@ -4478,7 +4495,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) - /* In the typical case, we are adding an skb to the end of the list. - * Use of ooo_last_skb avoids the O(Log(N)) rbtree lookup. - */ -- if (tcp_try_coalesce(sk, tp->ooo_last_skb, skb, &fragstolen)) { -+ if (tcp_ooo_try_coalesce(sk, tp->ooo_last_skb, -+ skb, &fragstolen)) { - coalesce_done: - tcp_grow_window(sk, skb); - kfree_skb_partial(skb, fragstolen); -@@ -4506,7 +4524,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) - /* All the bits are present. Drop. */ - NET_INC_STATS(sock_net(sk), - LINUX_MIB_TCPOFOMERGE); -- __kfree_skb(skb); -+ tcp_drop(sk, skb); - skb = NULL; - tcp_dsack_set(sk, seq, end_seq); - goto add_sack; -@@ -4525,10 +4543,11 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) - TCP_SKB_CB(skb1)->end_seq); - NET_INC_STATS(sock_net(sk), - LINUX_MIB_TCPOFOMERGE); -- __kfree_skb(skb1); -+ tcp_drop(sk, skb1); - goto merge_right; - } -- } else if (tcp_try_coalesce(sk, skb1, skb, &fragstolen)) { -+ } else if (tcp_ooo_try_coalesce(sk, skb1, -+ skb, &fragstolen)) { - goto coalesce_done; - } - p = &parent->rb_right; -@@ -4907,6 +4926,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, struct rb_root *root, - static void tcp_collapse_ofo_queue(struct sock *sk) - { - struct tcp_sock *tp = tcp_sk(sk); -+ u32 range_truesize, sum_tiny = 0; - struct sk_buff *skb, *head; - struct rb_node *p; - u32 start, end; -@@ -4925,6 +4945,7 @@ static void tcp_collapse_ofo_queue(struct sock *sk) - } - start = TCP_SKB_CB(skb)->seq; - end = TCP_SKB_CB(skb)->end_seq; -+ range_truesize = skb->truesize; - - for (head = skb;;) { - skb = tcp_skb_next(skb, NULL); -@@ -4935,11 +4956,20 @@ static void tcp_collapse_ofo_queue(struct sock *sk) - if (!skb || - after(TCP_SKB_CB(skb)->seq, end) || - before(TCP_SKB_CB(skb)->end_seq, start)) { -- tcp_collapse(sk, NULL, &tp->out_of_order_queue, -- head, skb, start, end); -+ /* Do not attempt collapsing tiny skbs */ -+ if (range_truesize != head->truesize || -+ end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) { -+ tcp_collapse(sk, NULL, &tp->out_of_order_queue, -+ head, skb, start, end); -+ } else { -+ sum_tiny += range_truesize; -+ if (sum_tiny > sk->sk_rcvbuf >> 3) -+ return; -+ } - goto new_range; - } - -+ range_truesize += skb->truesize; - if (unlikely(before(TCP_SKB_CB(skb)->seq, start))) - start = TCP_SKB_CB(skb)->seq; - if (after(TCP_SKB_CB(skb)->end_seq, end)) -@@ -4954,6 +4984,7 @@ static void tcp_collapse_ofo_queue(struct sock *sk) + #define skb_queue_walk(queue, skb) \ + for (skb = (queue)->next; \ + skb != (struct sk_buff *)(queue); \ +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 71f2b09..2eabf21 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -4965,6 +4965,7 @@ static void tcp_collapse_ofo_queue(struct sock *sk) * 2) not add too big latencies if thousands of packets sit there. * (But if application shrinks SO_RCVBUF, we could still end up * freeing whole queue here) @@ -136,7 +62,7 @@ index 2f107e4..4838b5f 100644 * * Return true if queue has shrunk. */ -@@ -4961,20 +4992,26 @@ static bool tcp_prune_ofo_queue(struct sock *sk) +@@ -4972,20 +4973,26 @@ static bool tcp_prune_ofo_queue(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); struct rb_node *node, *prev; @@ -167,16 +93,5 @@ index 2f107e4..4838b5f 100644 node = prev; } while (node); tp->ooo_last_skb = rb_entry(prev, struct sk_buff, rbnode); -@@ -5009,6 +5046,9 @@ static int tcp_prune_queue(struct sock *sk) - else if (tcp_under_memory_pressure(sk)) - tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); - -+ if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) -+ return 0; -+ - tcp_collapse_ofo_queue(sk); - if (!skb_queue_empty(&sk->sk_receive_queue)) - tcp_collapse(sk, &sk->sk_receive_queue, NULL, --- -- cgit v1.2.3-54-g00ecf