From: Greg Kroah-Hartman Date: Wed, 7 Jan 2015 01:38:34 +0000 (-0800) Subject: 3.17-stable patches X-Git-Tag: v3.10.64~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b80fea5c8fd573843727ceb8a6a1276996f31a26;p=thirdparty%2Fkernel%2Fstable-queue.git 3.17-stable patches added patches: audit-don-t-attempt-to-lookup-pids-when-changing-pid-filtering-audit-rules.patch audit-restore-audit_loginuid-unset-abi.patch audit-use-supplied-gfp_mask-from-audit_buffer-in-kauditd_send_multicast_skb.patch btrfs-do-not-move-em-to-modified-list-when-unpinning.patch btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch btrfs-fix-loop-writing-of-async-reclaim.patch btrfs-fix-wrong-accounting-of-raid1-data-profile-in-statfs.patch btrfs-make-sure-logged-extents-complete-in-the-current-transaction-v3.patch btrfs-make-sure-we-wait-on-logged-extents-when-fsycning-two-subvols.patch crypto-af_alg-fix-backlog-handling.patch ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch exit-pidns-alloc_pid-leaks-pid_namespace-if-child_reaper-is-exiting.patch ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch udf-check-component-length-before-reading-it.patch udf-check-path-length-when-reading-symlink.patch udf-verify-i_size-when-loading-inode.patch udf-verify-symlink-size-before-loading-it.patch --- diff --git a/queue-3.17/audit-don-t-attempt-to-lookup-pids-when-changing-pid-filtering-audit-rules.patch b/queue-3.17/audit-don-t-attempt-to-lookup-pids-when-changing-pid-filtering-audit-rules.patch new file mode 100644 index 00000000000..3ceab3d1c92 --- /dev/null +++ b/queue-3.17/audit-don-t-attempt-to-lookup-pids-when-changing-pid-filtering-audit-rules.patch @@ -0,0 +1,57 @@ +From 3640dcfa4fd00cd91d88bb86250bdb496f7070c0 Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Fri, 19 Dec 2014 18:35:53 -0500 +Subject: audit: don't attempt to lookup PIDs when changing PID filtering audit rules + +From: Paul Moore + +commit 3640dcfa4fd00cd91d88bb86250bdb496f7070c0 upstream. + +Commit f1dc4867 ("audit: anchor all pid references in the initial pid +namespace") introduced a find_vpid() call when adding/removing audit +rules with PID/PPID filters; unfortunately this is problematic as +find_vpid() only works if there is a task with the associated PID +alive on the system. The following commands demonstrate a simple +reproducer. + + # auditctl -D + # auditctl -l + # autrace /bin/true + # auditctl -l + +This patch resolves the problem by simply using the PID provided by +the user without any additional validation, e.g. no calls to check to +see if the task/PID exists. + +Cc: Richard Guy Briggs +Signed-off-by: Paul Moore +Acked-by: Eric Paris +Reviewed-by: Richard Guy Briggs +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/auditfilter.c | 13 ------------- + 1 file changed, 13 deletions(-) + +--- a/kernel/auditfilter.c ++++ b/kernel/auditfilter.c +@@ -433,19 +433,6 @@ static struct audit_entry *audit_data_to + f->val = 0; + } + +- if ((f->type == AUDIT_PID) || (f->type == AUDIT_PPID)) { +- struct pid *pid; +- rcu_read_lock(); +- pid = find_vpid(f->val); +- if (!pid) { +- rcu_read_unlock(); +- err = -ESRCH; +- goto exit_free; +- } +- f->val = pid_nr(pid); +- rcu_read_unlock(); +- } +- + err = audit_field_valid(entry, f); + if (err) + goto exit_free; diff --git a/queue-3.17/audit-restore-audit_loginuid-unset-abi.patch b/queue-3.17/audit-restore-audit_loginuid-unset-abi.patch new file mode 100644 index 00000000000..3e4dfa5b3d5 --- /dev/null +++ b/queue-3.17/audit-restore-audit_loginuid-unset-abi.patch @@ -0,0 +1,100 @@ +From 041d7b98ffe59c59fdd639931dea7d74f9aa9a59 Mon Sep 17 00:00:00 2001 +From: Richard Guy Briggs +Date: Tue, 23 Dec 2014 13:02:04 -0500 +Subject: audit: restore AUDIT_LOGINUID unset ABI + +From: Richard Guy Briggs + +commit 041d7b98ffe59c59fdd639931dea7d74f9aa9a59 upstream. + +A regression was caused by commit 780a7654cee8: + audit: Make testing for a valid loginuid explicit. +(which in turn attempted to fix a regression caused by e1760bd) + +When audit_krule_to_data() fills in the rules to get a listing, there was a +missing clause to convert back from AUDIT_LOGINUID_SET to AUDIT_LOGINUID. + +This broke userspace by not returning the same information that was sent and +expected. + +The rule: + auditctl -a exit,never -F auid=-1 +gives: + auditctl -l + LIST_RULES: exit,never f24=0 syscall=all +when it should give: + LIST_RULES: exit,never auid=-1 (0xffffffff) syscall=all + +Tag it so that it is reported the same way it was set. Create a new +private flags audit_krule field (pflags) to store it that won't interact with +the public one from the API. + +Signed-off-by: Richard Guy Briggs +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/audit.h | 4 ++++ + kernel/auditfilter.c | 10 ++++++++++ + 2 files changed, 14 insertions(+) + +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -47,6 +47,7 @@ struct sk_buff; + + struct audit_krule { + int vers_ops; ++ u32 pflags; + u32 flags; + u32 listnr; + u32 action; +@@ -64,6 +65,9 @@ struct audit_krule { + u64 prio; + }; + ++/* Flag to indicate legacy AUDIT_LOGINUID unset usage */ ++#define AUDIT_LOGINUID_LEGACY 0x1 ++ + struct audit_field { + u32 type; + u32 val; +--- a/kernel/auditfilter.c ++++ b/kernel/auditfilter.c +@@ -431,6 +431,7 @@ static struct audit_entry *audit_data_to + if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { + f->type = AUDIT_LOGINUID_SET; + f->val = 0; ++ entry->rule.pflags |= AUDIT_LOGINUID_LEGACY; + } + + err = audit_field_valid(entry, f); +@@ -606,6 +607,13 @@ static struct audit_rule_data *audit_kru + data->buflen += data->values[i] = + audit_pack_string(&bufp, krule->filterkey); + break; ++ case AUDIT_LOGINUID_SET: ++ if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) { ++ data->fields[i] = AUDIT_LOGINUID; ++ data->values[i] = AUDIT_UID_UNSET; ++ break; ++ } ++ /* fallthrough if set */ + default: + data->values[i] = f->val; + } +@@ -622,6 +630,7 @@ static int audit_compare_rule(struct aud + int i; + + if (a->flags != b->flags || ++ a->pflags != b->pflags || + a->listnr != b->listnr || + a->action != b->action || + a->field_count != b->field_count) +@@ -740,6 +749,7 @@ struct audit_entry *audit_dupe_rule(stru + new = &entry->rule; + new->vers_ops = old->vers_ops; + new->flags = old->flags; ++ new->pflags = old->pflags; + new->listnr = old->listnr; + new->action = old->action; + for (i = 0; i < AUDIT_BITMASK_SIZE; i++) diff --git a/queue-3.17/audit-use-supplied-gfp_mask-from-audit_buffer-in-kauditd_send_multicast_skb.patch b/queue-3.17/audit-use-supplied-gfp_mask-from-audit_buffer-in-kauditd_send_multicast_skb.patch new file mode 100644 index 00000000000..444d983da6b --- /dev/null +++ b/queue-3.17/audit-use-supplied-gfp_mask-from-audit_buffer-in-kauditd_send_multicast_skb.patch @@ -0,0 +1,94 @@ +From 54dc77d974a50147d6639dac6f59cb2c29207161 Mon Sep 17 00:00:00 2001 +From: Richard Guy Briggs +Date: Thu, 18 Dec 2014 23:09:27 -0500 +Subject: audit: use supplied gfp_mask from audit_buffer in kauditd_send_multicast_skb + +From: Richard Guy Briggs + +commit 54dc77d974a50147d6639dac6f59cb2c29207161 upstream. + +Eric Paris explains: Since kauditd_send_multicast_skb() gets called in +audit_log_end(), which can come from any context (aka even a sleeping context) +GFP_KERNEL can't be used. Since the audit_buffer knows what context it should +use, pass that down and use that. + +See: https://lkml.org/lkml/2014/12/16/542 + +BUG: sleeping function called from invalid context at mm/slab.c:2849 +in_atomic(): 1, irqs_disabled(): 0, pid: 885, name: sulogin +2 locks held by sulogin/885: + #0: (&sig->cred_guard_mutex){+.+.+.}, at: [] prepare_bprm_creds+0x28/0x8b + #1: (tty_files_lock){+.+.+.}, at: [] selinux_bprm_committing_creds+0x55/0x22b +CPU: 1 PID: 885 Comm: sulogin Not tainted 3.18.0-next-20141216 #30 +Hardware name: Dell Inc. Latitude E6530/07Y85M, BIOS A15 06/20/2014 + ffff880223744f10 ffff88022410f9b8 ffffffff916ba529 0000000000000375 + ffff880223744f10 ffff88022410f9e8 ffffffff91063185 0000000000000006 + 0000000000000000 0000000000000000 0000000000000000 ffff88022410fa38 +Call Trace: + [] dump_stack+0x50/0xa8 + [] ___might_sleep+0x1b6/0x1be + [] __might_sleep+0x119/0x128 + [] cache_alloc_debugcheck_before.isra.45+0x1d/0x1f + [] kmem_cache_alloc+0x43/0x1c9 + [] __alloc_skb+0x42/0x1a3 + [] skb_copy+0x3e/0xa3 + [] audit_log_end+0x83/0x100 + [] ? avc_audit_pre_callback+0x103/0x103 + [] common_lsm_audit+0x441/0x450 + [] slow_avc_audit+0x63/0x67 + [] avc_has_perm+0xca/0xe3 + [] inode_has_perm+0x5a/0x65 + [] selinux_bprm_committing_creds+0x98/0x22b + [] security_bprm_committing_creds+0xe/0x10 + [] install_exec_creds+0xe/0x79 + [] load_elf_binary+0xe36/0x10d7 + [] search_binary_handler+0x81/0x18c + [] do_execveat_common.isra.31+0x4e3/0x7b7 + [] do_execve+0x1f/0x21 + [] SyS_execve+0x25/0x29 + [] stub_execve+0x69/0xa0 + +Reported-by: Valdis Kletnieks +Signed-off-by: Richard Guy Briggs +Tested-by: Valdis Kletnieks +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/audit.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -429,7 +429,7 @@ static void kauditd_send_skb(struct sk_b + * This function doesn't consume an skb as might be expected since it has to + * copy it anyways. + */ +-static void kauditd_send_multicast_skb(struct sk_buff *skb) ++static void kauditd_send_multicast_skb(struct sk_buff *skb, gfp_t gfp_mask) + { + struct sk_buff *copy; + struct audit_net *aunet = net_generic(&init_net, audit_net_id); +@@ -448,11 +448,11 @@ static void kauditd_send_multicast_skb(s + * no reason for new multicast clients to continue with this + * non-compliance. + */ +- copy = skb_copy(skb, GFP_KERNEL); ++ copy = skb_copy(skb, gfp_mask); + if (!copy) + return; + +- nlmsg_multicast(sock, copy, 0, AUDIT_NLGRP_READLOG, GFP_KERNEL); ++ nlmsg_multicast(sock, copy, 0, AUDIT_NLGRP_READLOG, gfp_mask); + } + + /* +@@ -1959,7 +1959,7 @@ void audit_log_end(struct audit_buffer * + } else { + struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); + +- kauditd_send_multicast_skb(ab->skb); ++ kauditd_send_multicast_skb(ab->skb, ab->gfp_mask); + + /* + * The original kaudit unicast socket sends up messages with diff --git a/queue-3.17/btrfs-do-not-move-em-to-modified-list-when-unpinning.patch b/queue-3.17/btrfs-do-not-move-em-to-modified-list-when-unpinning.patch new file mode 100644 index 00000000000..15665f41d86 --- /dev/null +++ b/queue-3.17/btrfs-do-not-move-em-to-modified-list-when-unpinning.patch @@ -0,0 +1,55 @@ +From a28046956c71985046474283fa3bcd256915fb72 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 14 Nov 2014 16:16:30 -0500 +Subject: Btrfs: do not move em to modified list when unpinning + +From: Josef Bacik + +commit a28046956c71985046474283fa3bcd256915fb72 upstream. + +We use the modified list to keep track of which extents have been modified so we +know which ones are candidates for logging at fsync() time. Newly modified +extents are added to the list at modification time, around the same time the +ordered extent is created. We do this so that we don't have to wait for ordered +extents to complete before we know what we need to log. The problem is when +something like this happens + +log extent 0-4k on inode 1 +copy csum for 0-4k from ordered extent into log +sync log +commit transaction +log some other extent on inode 1 +ordered extent for 0-4k completes and adds itself onto modified list again +log changed extents +see ordered extent for 0-4k has already been logged + at this point we assume the csum has been copied +sync log +crash + +On replay we will see the extent 0-4k in the log, drop the original 0-4k extent +which is the same one that we are replaying which also drops the csum, and then +we won't find the csum in the log for that bytenr. This of course causes us to +have errors about not having csums for certain ranges of our inode. So remove +the modified list manipulation in unpin_extent_cache, any modified extents +should have been added well before now, and we don't want them re-logged. This +fixes my test that I could reliably reproduce this problem with. Thanks, + +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent_map.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/fs/btrfs/extent_map.c ++++ b/fs/btrfs/extent_map.c +@@ -287,8 +287,6 @@ int unpin_extent_cache(struct extent_map + if (!em) + goto out; + +- if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) +- list_move(&em->list, &tree->modified_extents); + em->generation = gen; + clear_bit(EXTENT_FLAG_PINNED, &em->flags); + em->mod_start = em->start; diff --git a/queue-3.17/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch b/queue-3.17/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch new file mode 100644 index 00000000000..0fe3d388e13 --- /dev/null +++ b/queue-3.17/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch @@ -0,0 +1,172 @@ +From 678886bdc6378c1cbd5072da2c5a3035000214e3 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Sun, 7 Dec 2014 21:31:47 +0000 +Subject: Btrfs: fix fs corruption on transaction abort if device supports discard + +From: Filipe Manana + +commit 678886bdc6378c1cbd5072da2c5a3035000214e3 upstream. + +When we abort a transaction we iterate over all the ranges marked as dirty +in fs_info->freed_extents[0] and fs_info->freed_extents[1], clear them +from those trees, add them back (unpin) to the free space caches and, if +the fs was mounted with "-o discard", perform a discard on those regions. +Also, after adding the regions to the free space caches, a fitrim ioctl call +can see those ranges in a block group's free space cache and perform a discard +on the ranges, so the same issue can happen without "-o discard" as well. + +This causes corruption, affecting one or multiple btree nodes (in the worst +case leaving the fs unmountable) because some of those ranges (the ones in +the fs_info->pinned_extents tree) correspond to btree nodes/leafs that are +referred by the last committed super block - breaking the rule that anything +that was committed by a transaction is untouched until the next transaction +commits successfully. + +I ran into this while running in a loop (for several hours) the fstest that +I recently submitted: + + [PATCH] fstests: add btrfs test to stress chunk allocation/removal and fstrim + +The corruption always happened when a transaction aborted and then fsck complained +like this: + + _check_btrfs_filesystem: filesystem on /dev/sdc is inconsistent + *** fsck.btrfs output *** + Check tree block failed, want=94945280, have=0 + Check tree block failed, want=94945280, have=0 + Check tree block failed, want=94945280, have=0 + Check tree block failed, want=94945280, have=0 + Check tree block failed, want=94945280, have=0 + read block failed check_tree_block + Couldn't open file system + +In this case 94945280 corresponded to the root of a tree. +Using frace what I observed was the following sequence of steps happened: + + 1) transaction N started, fs_info->pinned_extents pointed to + fs_info->freed_extents[0]; + + 2) node/eb 94945280 is created; + + 3) eb is persisted to disk; + + 4) transaction N commit starts, fs_info->pinned_extents now points to + fs_info->freed_extents[1], and transaction N completes; + + 5) transaction N + 1 starts; + + 6) eb is COWed, and btrfs_free_tree_block() called for this eb; + + 7) eb range (94945280 to 94945280 + 16Kb) is added to + fs_info->pinned_extents (fs_info->freed_extents[1]); + + 8) Something goes wrong in transaction N + 1, like hitting ENOSPC + for example, and the transaction is aborted, turning the fs into + readonly mode. The stack trace I got for example: + + [112065.253935] [] dump_stack+0x4d/0x66 + [112065.254271] [] warn_slowpath_common+0x7f/0x98 + [112065.254567] [] ? __btrfs_abort_transaction+0x50/0x10b [btrfs] + [112065.261674] [] warn_slowpath_fmt+0x48/0x50 + [112065.261922] [] ? btrfs_free_path+0x26/0x29 [btrfs] + [112065.262211] [] __btrfs_abort_transaction+0x50/0x10b [btrfs] + [112065.262545] [] btrfs_remove_chunk+0x537/0x58b [btrfs] + [112065.262771] [] btrfs_delete_unused_bgs+0x1de/0x21b [btrfs] + [112065.263105] [] cleaner_kthread+0x100/0x12f [btrfs] + (...) + [112065.264493] ---[ end trace dd7903a975a31a08 ]--- + [112065.264673] BTRFS: error (device sdc) in btrfs_remove_chunk:2625: errno=-28 No space left + [112065.264997] BTRFS info (device sdc): forced readonly + + 9) The clear kthread sees that the BTRFS_FS_STATE_ERROR bit is set in + fs_info->fs_state and calls btrfs_cleanup_transaction(), which in + turn calls btrfs_destroy_pinned_extent(); + + 10) Then btrfs_destroy_pinned_extent() iterates over all the ranges + marked as dirty in fs_info->freed_extents[], and for each one + it calls discard, if the fs was mounted with "-o discard", and + adds the range to the free space cache of the respective block + group; + + 11) btrfs_trim_block_group(), invoked from the fitrim ioctl code path, + sees the free space entries and performs a discard; + + 12) After an umount and mount (or fsck), our eb's location on disk was full + of zeroes, and it should have been untouched, because it was marked as + dirty in the fs_info->pinned_extents tree, and therefore used by the + trees that the last committed superblock points to. + +Fix this by not performing a discard and not adding the ranges to the free space +caches - it's useless from this point since the fs is now in readonly mode and +we won't write free space caches to disk anymore (otherwise we would leak space) +nor any new superblock. By not adding the ranges to the free space caches, it +prevents other code paths from allocating that space and write to it as well, +therefore being safer and simpler. + +This isn't a new problem, as it's been present since 2011 (git commit +acce952b0263825da32cf10489413dec78053347). + +Signed-off-by: Filipe Manana +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/disk-io.c | 6 ------ + fs/btrfs/extent-tree.c | 10 ++++++---- + 2 files changed, 6 insertions(+), 10 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4043,12 +4043,6 @@ again: + if (ret) + break; + +- /* opt_discard */ +- if (btrfs_test_opt(root, DISCARD)) +- ret = btrfs_error_discard_extent(root, start, +- end + 1 - start, +- NULL); +- + clear_extent_dirty(unpin, start, end, GFP_NOFS); + btrfs_error_unpin_extent_range(root, start, end); + cond_resched(); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5715,7 +5715,8 @@ void btrfs_prepare_extent_commit(struct + update_global_block_rsv(fs_info); + } + +-static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) ++static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, ++ const bool return_free_space) + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_group_cache *cache = NULL; +@@ -5739,7 +5740,8 @@ static int unpin_extent_range(struct btr + + if (start < cache->last_byte_to_unpin) { + len = min(len, cache->last_byte_to_unpin - start); +- btrfs_add_free_space(cache, start, len); ++ if (return_free_space) ++ btrfs_add_free_space(cache, start, len); + } + + start += len; +@@ -5803,7 +5805,7 @@ int btrfs_finish_extent_commit(struct bt + end + 1 - start, NULL); + + clear_extent_dirty(unpin, start, end, GFP_NOFS); +- unpin_extent_range(root, start, end); ++ unpin_extent_range(root, start, end, true); + cond_resched(); + } + +@@ -9487,7 +9489,7 @@ out: + + int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) + { +- return unpin_extent_range(root, start, end); ++ return unpin_extent_range(root, start, end, false); + } + + int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, diff --git a/queue-3.17/btrfs-fix-loop-writing-of-async-reclaim.patch b/queue-3.17/btrfs-fix-loop-writing-of-async-reclaim.patch new file mode 100644 index 00000000000..e07eb6fa5f1 --- /dev/null +++ b/queue-3.17/btrfs-fix-loop-writing-of-async-reclaim.patch @@ -0,0 +1,67 @@ +From 25ce459c1af138f95a3fd318461193397ebb825b Mon Sep 17 00:00:00 2001 +From: Liu Bo +Date: Wed, 10 Sep 2014 12:58:50 +0800 +Subject: Btrfs: fix loop writing of async reclaim + +From: Liu Bo + +commit 25ce459c1af138f95a3fd318461193397ebb825b upstream. + +One of my tests shows that when we really don't have space to reclaim via +flush_space and also run out of space, this async reclaim work loops on adding +itself into the workqueue and keeps writing something to disk according to +iostat's results, and these writes mainly comes from commit_transaction which +writes super_block. This's unacceptable as it can be bad to disks, especially +memeory storages. + +This adds a check to avoid the above situation. + +Signed-off-by: Liu Bo +Signed-off-by: Chris Mason +Cc: "Alexander E. Patrakov" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent-tree.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4343,11 +4343,21 @@ static inline int need_do_async_reclaim( + } + + static int btrfs_need_do_async_reclaim(struct btrfs_space_info *space_info, +- struct btrfs_fs_info *fs_info) ++ struct btrfs_fs_info *fs_info, ++ int flush_state) + { + u64 used; + + spin_lock(&space_info->lock); ++ /* ++ * We run out of space and have not got any free space via flush_space, ++ * so don't bother doing async reclaim. ++ */ ++ if (flush_state > COMMIT_TRANS && space_info->full) { ++ spin_unlock(&space_info->lock); ++ return 0; ++ } ++ + used = space_info->bytes_used + space_info->bytes_reserved + + space_info->bytes_pinned + space_info->bytes_readonly + + space_info->bytes_may_use; +@@ -4380,11 +4390,12 @@ static void btrfs_async_reclaim_metadata + flush_space(fs_info->fs_root, space_info, to_reclaim, + to_reclaim, flush_state); + flush_state++; +- if (!btrfs_need_do_async_reclaim(space_info, fs_info)) ++ if (!btrfs_need_do_async_reclaim(space_info, fs_info, ++ flush_state)) + return; + } while (flush_state <= COMMIT_TRANS); + +- if (btrfs_need_do_async_reclaim(space_info, fs_info)) ++ if (btrfs_need_do_async_reclaim(space_info, fs_info, flush_state)) + queue_work(system_unbound_wq, work); + } + diff --git a/queue-3.17/btrfs-fix-wrong-accounting-of-raid1-data-profile-in-statfs.patch b/queue-3.17/btrfs-fix-wrong-accounting-of-raid1-data-profile-in-statfs.patch new file mode 100644 index 00000000000..5caf147b3d1 --- /dev/null +++ b/queue-3.17/btrfs-fix-wrong-accounting-of-raid1-data-profile-in-statfs.patch @@ -0,0 +1,34 @@ +From 0d95c1bec906dd1ad951c9c001e798ca52baeb0f Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 14 Nov 2014 15:05:06 +0100 +Subject: btrfs: fix wrong accounting of raid1 data profile in statfs + +From: David Sterba + +commit 0d95c1bec906dd1ad951c9c001e798ca52baeb0f upstream. + +The sizes that are obtained from space infos are in raw units and have +to be adjusted according to the raid factor. This was missing for +f_bavail and df reported doubled size for raid1. + +Reported-by: Martin Steigerwald +Fixes: ba7b6e62f420 ("btrfs: adjust statfs calculations according to raid profiles") +Signed-off-by: David Sterba +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -1731,7 +1731,7 @@ static int btrfs_statfs(struct dentry *d + buf->f_bfree -= block_rsv->size >> bits; + spin_unlock(&block_rsv->lock); + +- buf->f_bavail = total_free_data; ++ buf->f_bavail = div_u64(total_free_data, factor); + ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data); + if (ret) { + mutex_unlock(&fs_info->chunk_mutex); diff --git a/queue-3.17/btrfs-make-sure-logged-extents-complete-in-the-current-transaction-v3.patch b/queue-3.17/btrfs-make-sure-logged-extents-complete-in-the-current-transaction-v3.patch new file mode 100644 index 00000000000..8abd87156d8 --- /dev/null +++ b/queue-3.17/btrfs-make-sure-logged-extents-complete-in-the-current-transaction-v3.patch @@ -0,0 +1,273 @@ +From 50d9aa99bd35c77200e0e3dd7a72274f8304701f Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 21 Nov 2014 14:52:38 -0500 +Subject: Btrfs: make sure logged extents complete in the current transaction V3 + +From: Josef Bacik + +commit 50d9aa99bd35c77200e0e3dd7a72274f8304701f upstream. + +Liu Bo pointed out that my previous fix would lose the generation update in the +scenario I described. It is actually much worse than that, we could lose the +entire extent if we lose power right after the transaction commits. Consider +the following + +write extent 0-4k +log extent in log tree +commit transaction + < power fail happens here +ordered extent completes + +We would lose the 0-4k extent because it hasn't updated the actual fs tree, and +the transaction commit will reset the log so it isn't replayed. If we lose +power before the transaction commit we are save, otherwise we are not. + +Fix this by keeping track of all extents we logged in this transaction. Then +when we go to commit the transaction make sure we wait for all of those ordered +extents to complete before proceeding. This will make sure that if we lose +power after the transaction commit we still have our data. This also fixes the +problem of the improperly updated extent generation. Thanks, + +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/disk-io.c | 20 ++++++++++++++++++++ + fs/btrfs/ordered-data.c | 9 +++++++-- + fs/btrfs/ordered-data.h | 8 +++++++- + fs/btrfs/transaction.c | 33 +++++++++++++++++++++++++++++++++ + fs/btrfs/transaction.h | 2 ++ + fs/btrfs/tree-log.c | 6 +++--- + 6 files changed, 72 insertions(+), 6 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4066,6 +4066,25 @@ again: + return 0; + } + ++static void btrfs_free_pending_ordered(struct btrfs_transaction *cur_trans, ++ struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_ordered_extent *ordered; ++ ++ spin_lock(&fs_info->trans_lock); ++ while (!list_empty(&cur_trans->pending_ordered)) { ++ ordered = list_first_entry(&cur_trans->pending_ordered, ++ struct btrfs_ordered_extent, ++ trans_list); ++ list_del_init(&ordered->trans_list); ++ spin_unlock(&fs_info->trans_lock); ++ ++ btrfs_put_ordered_extent(ordered); ++ spin_lock(&fs_info->trans_lock); ++ } ++ spin_unlock(&fs_info->trans_lock); ++} ++ + void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, + struct btrfs_root *root) + { +@@ -4077,6 +4096,7 @@ void btrfs_cleanup_one_transaction(struc + cur_trans->state = TRANS_STATE_UNBLOCKED; + wake_up(&root->fs_info->transaction_wait); + ++ btrfs_free_pending_ordered(cur_trans, root->fs_info); + btrfs_destroy_delayed_inodes(root); + btrfs_assert_delayed_root_empty(root); + +--- a/fs/btrfs/ordered-data.c ++++ b/fs/btrfs/ordered-data.c +@@ -220,6 +220,7 @@ static int __btrfs_add_ordered_extent(st + INIT_LIST_HEAD(&entry->work_list); + init_completion(&entry->completion); + INIT_LIST_HEAD(&entry->log_list); ++ INIT_LIST_HEAD(&entry->trans_list); + + trace_btrfs_ordered_extent_add(inode, entry); + +@@ -443,6 +444,8 @@ void btrfs_get_logged_extents(struct ino + ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); + if (!list_empty(&ordered->log_list)) + continue; ++ if (test_bit(BTRFS_ORDERED_LOGGED, &ordered->flags)) ++ continue; + list_add_tail(&ordered->log_list, logged_list); + atomic_inc(&ordered->refs); + } +@@ -472,7 +475,8 @@ void btrfs_submit_logged_extents(struct + spin_unlock_irq(&log->log_extents_lock[index]); + } + +-void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid) ++void btrfs_wait_logged_extents(struct btrfs_trans_handle *trans, ++ struct btrfs_root *log, u64 transid) + { + struct btrfs_ordered_extent *ordered; + int index = transid % 2; +@@ -497,7 +501,8 @@ void btrfs_wait_logged_extents(struct bt + wait_event(ordered->wait, test_bit(BTRFS_ORDERED_IO_DONE, + &ordered->flags)); + +- btrfs_put_ordered_extent(ordered); ++ if (!test_and_set_bit(BTRFS_ORDERED_LOGGED, &ordered->flags)) ++ list_add_tail(&ordered->trans_list, &trans->ordered); + spin_lock_irq(&log->log_extents_lock[index]); + } + spin_unlock_irq(&log->log_extents_lock[index]); +--- a/fs/btrfs/ordered-data.h ++++ b/fs/btrfs/ordered-data.h +@@ -71,6 +71,8 @@ struct btrfs_ordered_sum { + ordered extent */ + #define BTRFS_ORDERED_TRUNCATED 9 /* Set when we have to truncate an extent */ + ++#define BTRFS_ORDERED_LOGGED 10 /* Set when we've waited on this ordered extent ++ * in the logging code. */ + struct btrfs_ordered_extent { + /* logical offset in the file */ + u64 file_offset; +@@ -121,6 +123,9 @@ struct btrfs_ordered_extent { + /* If we need to wait on this to be done */ + struct list_head log_list; + ++ /* If the transaction needs to wait on this ordered extent */ ++ struct list_head trans_list; ++ + /* used to wait for the BTRFS_ORDERED_COMPLETE bit */ + wait_queue_head_t wait; + +@@ -197,7 +202,8 @@ void btrfs_get_logged_extents(struct ino + void btrfs_put_logged_extents(struct list_head *logged_list); + void btrfs_submit_logged_extents(struct list_head *logged_list, + struct btrfs_root *log); +-void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid); ++void btrfs_wait_logged_extents(struct btrfs_trans_handle *trans, ++ struct btrfs_root *log, u64 transid); + void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid); + int __init ordered_data_init(void); + void ordered_data_exit(void); +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -220,6 +220,7 @@ loop: + INIT_LIST_HEAD(&cur_trans->pending_snapshots); + INIT_LIST_HEAD(&cur_trans->pending_chunks); + INIT_LIST_HEAD(&cur_trans->switch_commits); ++ INIT_LIST_HEAD(&cur_trans->pending_ordered); + list_add_tail(&cur_trans->list, &fs_info->trans_list); + extent_io_tree_init(&cur_trans->dirty_pages, + fs_info->btree_inode->i_mapping); +@@ -488,6 +489,7 @@ again: + h->sync = false; + INIT_LIST_HEAD(&h->qgroup_ref_list); + INIT_LIST_HEAD(&h->new_bgs); ++ INIT_LIST_HEAD(&h->ordered); + + smp_mb(); + if (cur_trans->state >= TRANS_STATE_BLOCKED && +@@ -719,6 +721,12 @@ static int __btrfs_end_transaction(struc + if (!list_empty(&trans->new_bgs)) + btrfs_create_pending_block_groups(trans, root); + ++ if (!list_empty(&trans->ordered)) { ++ spin_lock(&info->trans_lock); ++ list_splice(&trans->ordered, &cur_trans->pending_ordered); ++ spin_unlock(&info->trans_lock); ++ } ++ + trans->delayed_ref_updates = 0; + if (!trans->sync) { + must_run_delayed_refs = +@@ -1630,6 +1638,28 @@ static inline void btrfs_wait_delalloc_f + btrfs_wait_ordered_roots(fs_info, -1); + } + ++static inline void ++btrfs_wait_pending_ordered(struct btrfs_transaction *cur_trans, ++ struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_ordered_extent *ordered; ++ ++ spin_lock(&fs_info->trans_lock); ++ while (!list_empty(&cur_trans->pending_ordered)) { ++ ordered = list_first_entry(&cur_trans->pending_ordered, ++ struct btrfs_ordered_extent, ++ trans_list); ++ list_del_init(&ordered->trans_list); ++ spin_unlock(&fs_info->trans_lock); ++ ++ wait_event(ordered->wait, test_bit(BTRFS_ORDERED_COMPLETE, ++ &ordered->flags)); ++ btrfs_put_ordered_extent(ordered); ++ spin_lock(&fs_info->trans_lock); ++ } ++ spin_unlock(&fs_info->trans_lock); ++} ++ + int btrfs_commit_transaction(struct btrfs_trans_handle *trans, + struct btrfs_root *root) + { +@@ -1679,6 +1709,7 @@ int btrfs_commit_transaction(struct btrf + } + + spin_lock(&root->fs_info->trans_lock); ++ list_splice(&trans->ordered, &cur_trans->pending_ordered); + if (cur_trans->state >= TRANS_STATE_COMMIT_START) { + spin_unlock(&root->fs_info->trans_lock); + atomic_inc(&cur_trans->use_count); +@@ -1731,6 +1762,8 @@ int btrfs_commit_transaction(struct btrf + + btrfs_wait_delalloc_flush(root->fs_info); + ++ btrfs_wait_pending_ordered(cur_trans, root->fs_info); ++ + btrfs_scrub_pause(root); + /* + * Ok now we need to make sure to block out any other joins while we +--- a/fs/btrfs/transaction.h ++++ b/fs/btrfs/transaction.h +@@ -56,6 +56,7 @@ struct btrfs_transaction { + wait_queue_head_t commit_wait; + struct list_head pending_snapshots; + struct list_head pending_chunks; ++ struct list_head pending_ordered; + struct list_head switch_commits; + struct btrfs_delayed_ref_root delayed_refs; + int aborted; +@@ -105,6 +106,7 @@ struct btrfs_trans_handle { + */ + struct btrfs_root *root; + struct seq_list delayed_ref_elem; ++ struct list_head ordered; + struct list_head qgroup_ref_list; + struct list_head new_bgs; + }; +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -2598,7 +2598,7 @@ int btrfs_sync_log(struct btrfs_trans_ha + if (atomic_read(&log_root_tree->log_commit[index2])) { + blk_finish_plug(&plug); + btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); +- btrfs_wait_logged_extents(log, log_transid); ++ btrfs_wait_logged_extents(trans, log, log_transid); + wait_log_commit(trans, log_root_tree, + root_log_ctx.log_transid); + mutex_unlock(&log_root_tree->log_mutex); +@@ -2643,7 +2643,7 @@ int btrfs_sync_log(struct btrfs_trans_ha + btrfs_wait_marked_extents(log_root_tree, + &log_root_tree->dirty_log_pages, + EXTENT_NEW | EXTENT_DIRTY); +- btrfs_wait_logged_extents(log, log_transid); ++ btrfs_wait_logged_extents(trans, log, log_transid); + + btrfs_set_super_log_root(root->fs_info->super_for_commit, + log_root_tree->node->start); +@@ -3618,7 +3618,7 @@ static int log_one_extent(struct btrfs_t + fi = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_file_extent_item); + +- btrfs_set_token_file_extent_generation(leaf, fi, em->generation, ++ btrfs_set_token_file_extent_generation(leaf, fi, trans->transid, + &token); + if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) { + skip_csum = true; diff --git a/queue-3.17/btrfs-make-sure-we-wait-on-logged-extents-when-fsycning-two-subvols.patch b/queue-3.17/btrfs-make-sure-we-wait-on-logged-extents-when-fsycning-two-subvols.patch new file mode 100644 index 00000000000..64c2b23244f --- /dev/null +++ b/queue-3.17/btrfs-make-sure-we-wait-on-logged-extents-when-fsycning-two-subvols.patch @@ -0,0 +1,37 @@ +From 9dba8cf128ef98257ca719722280c9634e7e9dc7 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Thu, 6 Nov 2014 10:19:54 -0500 +Subject: Btrfs: make sure we wait on logged extents when fsycning two subvols + +From: Josef Bacik + +commit 9dba8cf128ef98257ca719722280c9634e7e9dc7 upstream. + +If we have two fsync()'s race on different subvols one will do all of its work +to get into the log_tree, wait on it's outstanding IO, and then allow the +log_tree to finish it's commit. The problem is we were just free'ing that +subvols logged extents instead of waiting on them, so whoever lost the race +wouldn't really have their data on disk. Fix this by waiting properly instead +of freeing the logged extents. Thanks, + +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-log.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -2598,9 +2598,9 @@ int btrfs_sync_log(struct btrfs_trans_ha + if (atomic_read(&log_root_tree->log_commit[index2])) { + blk_finish_plug(&plug); + btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); ++ btrfs_wait_logged_extents(log, log_transid); + wait_log_commit(trans, log_root_tree, + root_log_ctx.log_transid); +- btrfs_free_logged_extents(log, log_transid); + mutex_unlock(&log_root_tree->log_mutex); + ret = root_log_ctx.log_ret; + goto out; diff --git a/queue-3.17/crypto-af_alg-fix-backlog-handling.patch b/queue-3.17/crypto-af_alg-fix-backlog-handling.patch new file mode 100644 index 00000000000..67ba40de99a --- /dev/null +++ b/queue-3.17/crypto-af_alg-fix-backlog-handling.patch @@ -0,0 +1,48 @@ +From 7e77bdebff5cb1e9876c561f69710b9ab8fa1f7e Mon Sep 17 00:00:00 2001 +From: Rabin Vincent +Date: Fri, 19 Dec 2014 13:36:08 +0100 +Subject: crypto: af_alg - fix backlog handling + +From: Rabin Vincent + +commit 7e77bdebff5cb1e9876c561f69710b9ab8fa1f7e upstream. + +If a request is backlogged, it's complete() handler will get called +twice: once with -EINPROGRESS, and once with the final error code. + +af_alg's complete handler, unlike other users, does not handle the +-EINPROGRESS but instead always completes the completion that recvmsg() +is waiting on. This can lead to a return to user space while the +request is still pending in the driver. If userspace closes the sockets +before the requests are handled by the driver, this will lead to +use-after-frees (and potential crashes) in the kernel due to the tfm +having been freed. + +The crashes can be easily reproduced (for example) by reducing the max +queue length in cryptod.c and running the following (from +http://www.chronox.de/libkcapi.html) on AES-NI capable hardware: + + $ while true; do kcapi -x 1 -e -c '__ecb-aes-aesni' \ + -k 00000000000000000000000000000000 \ + -p 00000000000000000000000000000000 >/dev/null & done + +Signed-off-by: Rabin Vincent +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/af_alg.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -449,6 +449,9 @@ void af_alg_complete(struct crypto_async + { + struct af_alg_completion *completion = req->data; + ++ if (err == -EINPROGRESS) ++ return; ++ + completion->err = err; + complete(&completion->completion); + } diff --git a/queue-3.17/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch b/queue-3.17/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch new file mode 100644 index 00000000000..e76a8f17597 --- /dev/null +++ b/queue-3.17/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch @@ -0,0 +1,103 @@ +From 332b122d39c9cbff8b799007a825d94b2e7c12f2 Mon Sep 17 00:00:00 2001 +From: Tyler Hicks +Date: Tue, 7 Oct 2014 15:51:55 -0500 +Subject: eCryptfs: Force RO mount when encrypted view is enabled + +From: Tyler Hicks + +commit 332b122d39c9cbff8b799007a825d94b2e7c12f2 upstream. + +The ecryptfs_encrypted_view mount option greatly changes the +functionality of an eCryptfs mount. Instead of encrypting and decrypting +lower files, it provides a unified view of the encrypted files in the +lower filesystem. The presence of the ecryptfs_encrypted_view mount +option is intended to force a read-only mount and modifying files is not +supported when the feature is in use. See the following commit for more +information: + + e77a56d [PATCH] eCryptfs: Encrypted passthrough + +This patch forces the mount to be read-only when the +ecryptfs_encrypted_view mount option is specified by setting the +MS_RDONLY flag on the superblock. Additionally, this patch removes some +broken logic in ecryptfs_open() that attempted to prevent modifications +of files when the encrypted view feature was in use. The check in +ecryptfs_open() was not sufficient to prevent file modifications using +system calls that do not operate on a file descriptor. + +Signed-off-by: Tyler Hicks +Reported-by: Priya Bansal +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/file.c | 12 ------------ + fs/ecryptfs/main.c | 16 +++++++++++++--- + 2 files changed, 13 insertions(+), 15 deletions(-) + +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -190,23 +190,11 @@ static int ecryptfs_open(struct inode *i + { + int rc = 0; + struct ecryptfs_crypt_stat *crypt_stat = NULL; +- struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct dentry *ecryptfs_dentry = file->f_path.dentry; + /* Private value of ecryptfs_dentry allocated in + * ecryptfs_lookup() */ + struct ecryptfs_file_info *file_info; + +- mount_crypt_stat = &ecryptfs_superblock_to_private( +- ecryptfs_dentry->d_sb)->mount_crypt_stat; +- if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) +- && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) +- || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) +- || (file->f_flags & O_APPEND))) { +- printk(KERN_WARNING "Mount has encrypted view enabled; " +- "files may only be read\n"); +- rc = -EPERM; +- goto out; +- } + /* Released in ecryptfs_release or end of function if failure */ + file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); + ecryptfs_set_file_private(file, file_info); +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -493,6 +493,7 @@ static struct dentry *ecryptfs_mount(str + { + struct super_block *s; + struct ecryptfs_sb_info *sbi; ++ struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_dentry_info *root_info; + const char *err = "Getting sb failed"; + struct inode *inode; +@@ -511,6 +512,7 @@ static struct dentry *ecryptfs_mount(str + err = "Error parsing options"; + goto out; + } ++ mount_crypt_stat = &sbi->mount_crypt_stat; + + s = sget(fs_type, NULL, set_anon_super, flags, NULL); + if (IS_ERR(s)) { +@@ -557,11 +559,19 @@ static struct dentry *ecryptfs_mount(str + + /** + * Set the POSIX ACL flag based on whether they're enabled in the lower +- * mount. Force a read-only eCryptfs mount if the lower mount is ro. +- * Allow a ro eCryptfs mount even when the lower mount is rw. ++ * mount. + */ + s->s_flags = flags & ~MS_POSIXACL; +- s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); ++ s->s_flags |= path.dentry->d_sb->s_flags & MS_POSIXACL; ++ ++ /** ++ * Force a read-only eCryptfs mount when: ++ * 1) The lower mount is ro ++ * 2) The ecryptfs_encrypted_view mount option is specified ++ */ ++ if (path.dentry->d_sb->s_flags & MS_RDONLY || ++ mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) ++ s->s_flags |= MS_RDONLY; + + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; + s->s_blocksize = path.dentry->d_sb->s_blocksize; diff --git a/queue-3.17/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch b/queue-3.17/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch new file mode 100644 index 00000000000..64b4ea9cc0d --- /dev/null +++ b/queue-3.17/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch @@ -0,0 +1,34 @@ +From 942080643bce061c3dd9d5718d3b745dcb39a8bc Mon Sep 17 00:00:00 2001 +From: Michael Halcrow +Date: Wed, 26 Nov 2014 09:09:16 -0800 +Subject: eCryptfs: Remove buggy and unnecessary write in file name decode routine + +From: Michael Halcrow + +commit 942080643bce061c3dd9d5718d3b745dcb39a8bc upstream. + +Dmitry Chernenkov used KASAN to discover that eCryptfs writes past the +end of the allocated buffer during encrypted filename decoding. This +fix corrects the issue by getting rid of the unnecessary 0 write when +the current bit offset is 2. + +Signed-off-by: Michael Halcrow +Reported-by: Dmitry Chernenkov +Suggested-by: Kees Cook +Signed-off-by: Tyler Hicks +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/crypto.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -1917,7 +1917,6 @@ ecryptfs_decode_from_filename(unsigned c + break; + case 2: + dst[dst_byte_offset++] |= (src_byte); +- dst[dst_byte_offset] = 0; + current_bit_offset = 0; + break; + } diff --git a/queue-3.17/exit-pidns-alloc_pid-leaks-pid_namespace-if-child_reaper-is-exiting.patch b/queue-3.17/exit-pidns-alloc_pid-leaks-pid_namespace-if-child_reaper-is-exiting.patch new file mode 100644 index 00000000000..ad23c056280 --- /dev/null +++ b/queue-3.17/exit-pidns-alloc_pid-leaks-pid_namespace-if-child_reaper-is-exiting.patch @@ -0,0 +1,41 @@ +From 24c037ebf5723d4d9ab0996433cee4f96c292a4d Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Wed, 10 Dec 2014 15:55:25 -0800 +Subject: exit: pidns: alloc_pid() leaks pid_namespace if child_reaper is exiting + +From: Oleg Nesterov + +commit 24c037ebf5723d4d9ab0996433cee4f96c292a4d upstream. + +alloc_pid() does get_pid_ns() beforehand but forgets to put_pid_ns() if it +fails because disable_pid_allocation() was called by the exiting +child_reaper. + +We could simply move get_pid_ns() down to successful return, but this fix +tries to be as trivial as possible. + +Signed-off-by: Oleg Nesterov +Reviewed-by: "Eric W. Biederman" +Cc: Aaron Tomlin +Cc: Pavel Emelyanov +Cc: Serge Hallyn +Cc: Sterling Alexander +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/pid.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/kernel/pid.c ++++ b/kernel/pid.c +@@ -341,6 +341,8 @@ out: + + out_unlock: + spin_unlock_irq(&pidmap_lock); ++ put_pid_ns(ns); ++ + out_free: + while (++i <= ns->level) + free_pidmap(pid->numbers + i); diff --git a/queue-3.17/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch b/queue-3.17/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch new file mode 100644 index 00000000000..2dd9140b277 --- /dev/null +++ b/queue-3.17/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch @@ -0,0 +1,39 @@ +From a682e9c28cac152e6e54c39efcf046e0c8cfcf63 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 10 Dec 2014 15:52:22 -0800 +Subject: ncpfs: return proper error from NCP_IOC_SETROOT ioctl + +From: Jan Kara + +commit a682e9c28cac152e6e54c39efcf046e0c8cfcf63 upstream. + +If some error happens in NCP_IOC_SETROOT ioctl, the appropriate error +return value is then (in most cases) just overwritten before we return. +This can result in reporting success to userspace although error happened. + +This bug was introduced by commit 2e54eb96e2c8 ("BKL: Remove BKL from +ncpfs"). Propagate the errors correctly. + +Coverity id: 1226925. + +Fixes: 2e54eb96e2c80 ("BKL: Remove BKL from ncpfs") +Signed-off-by: Jan Kara +Cc: Petr Vandrovec +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ncpfs/ioctl.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/ncpfs/ioctl.c ++++ b/fs/ncpfs/ioctl.c +@@ -447,7 +447,6 @@ static long __ncp_ioctl(struct inode *in + result = -EIO; + } + } +- result = 0; + } + mutex_unlock(&server->root_setup_lock); + diff --git a/queue-3.17/series b/queue-3.17/series index 1c36472a466..d7fbf82284d 100644 --- a/queue-3.17/series +++ b/queue-3.17/series @@ -53,3 +53,21 @@ userns-rename-id_map_mutex-to-userns_state_mutex.patch userns-add-a-knob-to-disable-setgroups-on-a-per-user-namespace-basis.patch userns-allow-setting-gid_maps-without-privilege-when-setgroups-is-disabled.patch userns-unbreak-the-unprivileged-remount-tests.patch +audit-use-supplied-gfp_mask-from-audit_buffer-in-kauditd_send_multicast_skb.patch +audit-don-t-attempt-to-lookup-pids-when-changing-pid-filtering-audit-rules.patch +audit-restore-audit_loginuid-unset-abi.patch +crypto-af_alg-fix-backlog-handling.patch +ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch +exit-pidns-alloc_pid-leaks-pid_namespace-if-child_reaper-is-exiting.patch +udf-check-path-length-when-reading-symlink.patch +udf-verify-i_size-when-loading-inode.patch +udf-verify-symlink-size-before-loading-it.patch +udf-check-component-length-before-reading-it.patch +ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch +ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch +btrfs-make-sure-we-wait-on-logged-extents-when-fsycning-two-subvols.patch +btrfs-fix-wrong-accounting-of-raid1-data-profile-in-statfs.patch +btrfs-do-not-move-em-to-modified-list-when-unpinning.patch +btrfs-make-sure-logged-extents-complete-in-the-current-transaction-v3.patch +btrfs-fix-loop-writing-of-async-reclaim.patch +btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch diff --git a/queue-3.17/udf-check-component-length-before-reading-it.patch b/queue-3.17/udf-check-component-length-before-reading-it.patch new file mode 100644 index 00000000000..157bfecf68f --- /dev/null +++ b/queue-3.17/udf-check-component-length-before-reading-it.patch @@ -0,0 +1,61 @@ +From e237ec37ec154564f8690c5bd1795339955eeef9 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 19 Dec 2014 14:27:55 +0100 +Subject: udf: Check component length before reading it + +From: Jan Kara + +commit e237ec37ec154564f8690c5bd1795339955eeef9 upstream. + +Check that length specified in a component of a symlink fits in the +input buffer we are reading. Also properly ignore component length for +component types that do not use it. Otherwise we read memory after end +of buffer for corrupted udf image. + +Reported-by: Carl Henrik Lunde +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/symlink.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -42,14 +42,17 @@ static int udf_pc_to_char(struct super_b + tolen--; + while (elen < fromlen) { + pc = (struct pathComponent *)(from + elen); ++ elen += sizeof(struct pathComponent); + switch (pc->componentType) { + case 1: + /* + * Symlink points to some place which should be agreed + * upon between originator and receiver of the media. Ignore. + */ +- if (pc->lengthComponentIdent > 0) ++ if (pc->lengthComponentIdent > 0) { ++ elen += pc->lengthComponentIdent; + break; ++ } + /* Fall through */ + case 2: + if (tolen == 0) +@@ -74,6 +77,9 @@ static int udf_pc_to_char(struct super_b + /* that would be . - just ignore */ + break; + case 5: ++ elen += pc->lengthComponentIdent; ++ if (elen > fromlen) ++ return -EIO; + comp_len = udf_get_filename(sb, pc->componentIdent, + pc->lengthComponentIdent, + p, tolen); +@@ -85,7 +91,6 @@ static int udf_pc_to_char(struct super_b + tolen--; + break; + } +- elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; + } + if (p > to + 1) + p[-1] = '\0'; diff --git a/queue-3.17/udf-check-path-length-when-reading-symlink.patch b/queue-3.17/udf-check-path-length-when-reading-symlink.patch new file mode 100644 index 00000000000..915ef3c965d --- /dev/null +++ b/queue-3.17/udf-check-path-length-when-reading-symlink.patch @@ -0,0 +1,228 @@ +From 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 18 Dec 2014 22:37:50 +0100 +Subject: udf: Check path length when reading symlink + +From: Jan Kara + +commit 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 upstream. + +Symlink reading code does not check whether the resulting path fits into +the page provided by the generic code. This isn't as easy as just +checking the symlink size because of various encoding conversions we +perform on path. So we have to check whether there is still enough space +in the buffer on the fly. + +Reported-by: Carl Henrik Lunde +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/dir.c | 3 ++- + fs/udf/namei.c | 3 ++- + fs/udf/symlink.c | 31 ++++++++++++++++++++++++++----- + fs/udf/udfdecl.h | 3 ++- + fs/udf/unicode.c | 28 ++++++++++++++++------------ + 5 files changed, 48 insertions(+), 20 deletions(-) + +--- a/fs/udf/dir.c ++++ b/fs/udf/dir.c +@@ -167,7 +167,8 @@ static int udf_readdir(struct file *file + continue; + } + +- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); ++ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, ++ UDF_NAME_LEN); + if (!flen) + continue; + +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -233,7 +233,8 @@ static struct fileIdentDesc *udf_find_en + if (!lfi) + continue; + +- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); ++ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, ++ UDF_NAME_LEN); + if (flen && udf_match(flen, fname, child->len, child->name)) + goto out_ok; + } +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -30,13 +30,16 @@ + #include + #include "udf_i.h" + +-static void udf_pc_to_char(struct super_block *sb, unsigned char *from, +- int fromlen, unsigned char *to) ++static int udf_pc_to_char(struct super_block *sb, unsigned char *from, ++ int fromlen, unsigned char *to, int tolen) + { + struct pathComponent *pc; + int elen = 0; ++ int comp_len; + unsigned char *p = to; + ++ /* Reserve one byte for terminating \0 */ ++ tolen--; + while (elen < fromlen) { + pc = (struct pathComponent *)(from + elen); + switch (pc->componentType) { +@@ -49,22 +52,37 @@ static void udf_pc_to_char(struct super_ + break; + /* Fall through */ + case 2: ++ if (tolen == 0) ++ return -ENAMETOOLONG; + p = to; + *p++ = '/'; ++ tolen--; + break; + case 3: ++ if (tolen < 3) ++ return -ENAMETOOLONG; + memcpy(p, "../", 3); + p += 3; ++ tolen -= 3; + break; + case 4: ++ if (tolen < 2) ++ return -ENAMETOOLONG; + memcpy(p, "./", 2); + p += 2; ++ tolen -= 2; + /* that would be . - just ignore */ + break; + case 5: +- p += udf_get_filename(sb, pc->componentIdent, p, +- pc->lengthComponentIdent); ++ comp_len = udf_get_filename(sb, pc->componentIdent, ++ pc->lengthComponentIdent, ++ p, tolen); ++ p += comp_len; ++ tolen -= comp_len; ++ if (tolen == 0) ++ return -ENAMETOOLONG; + *p++ = '/'; ++ tolen--; + break; + } + elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; +@@ -73,6 +91,7 @@ static void udf_pc_to_char(struct super_ + p[-1] = '\0'; + else + p[0] = '\0'; ++ return 0; + } + + static int udf_symlink_filler(struct file *file, struct page *page) +@@ -100,8 +119,10 @@ static int udf_symlink_filler(struct fil + symlink = bh->b_data; + } + +- udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); ++ err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); + brelse(bh); ++ if (err) ++ goto out_unlock_inode; + + up_read(&iinfo->i_data_sem); + SetPageUptodate(page); +--- a/fs/udf/udfdecl.h ++++ b/fs/udf/udfdecl.h +@@ -211,7 +211,8 @@ udf_get_lb_pblock(struct super_block *sb + } + + /* unicode.c */ +-extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); ++extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *, ++ int); + extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, + int); + extern int udf_build_ustr(struct ustr *, dstring *, int); +--- a/fs/udf/unicode.c ++++ b/fs/udf/unicode.c +@@ -28,7 +28,8 @@ + + #include "udf_sb.h" + +-static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); ++static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *, ++ int); + + static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) + { +@@ -333,8 +334,8 @@ try_again: + return u_len + 1; + } + +-int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, +- int flen) ++int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, ++ uint8_t *dname, int dlen) + { + struct ustr *filename, *unifilename; + int len = 0; +@@ -347,7 +348,7 @@ int udf_get_filename(struct super_block + if (!unifilename) + goto out1; + +- if (udf_build_ustr_exact(unifilename, sname, flen)) ++ if (udf_build_ustr_exact(unifilename, sname, slen)) + goto out2; + + if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { +@@ -366,7 +367,8 @@ int udf_get_filename(struct super_block + } else + goto out2; + +- len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, ++ len = udf_translate_to_linux(dname, dlen, ++ filename->u_name, filename->u_len, + unifilename->u_name, unifilename->u_len); + out2: + kfree(unifilename); +@@ -403,10 +405,12 @@ int udf_put_filename(struct super_block + #define EXT_MARK '.' + #define CRC_MARK '#' + #define EXT_SIZE 5 ++/* Number of chars we need to store generated CRC to make filename unique */ ++#define CRC_LEN 5 + +-static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, +- int udfLen, uint8_t *fidName, +- int fidNameLen) ++static int udf_translate_to_linux(uint8_t *newName, int newLen, ++ uint8_t *udfName, int udfLen, ++ uint8_t *fidName, int fidNameLen) + { + int index, newIndex = 0, needsCRC = 0; + int extIndex = 0, newExtIndex = 0, hasExt = 0; +@@ -439,7 +443,7 @@ static int udf_translate_to_linux(uint8_ + newExtIndex = newIndex; + } + } +- if (newIndex < 256) ++ if (newIndex < newLen) + newName[newIndex++] = curr; + else + needsCRC = 1; +@@ -467,13 +471,13 @@ static int udf_translate_to_linux(uint8_ + } + ext[localExtIndex++] = curr; + } +- maxFilenameLen = 250 - localExtIndex; ++ maxFilenameLen = newLen - CRC_LEN - localExtIndex; + if (newIndex > maxFilenameLen) + newIndex = maxFilenameLen; + else + newIndex = newExtIndex; +- } else if (newIndex > 250) +- newIndex = 250; ++ } else if (newIndex > newLen - CRC_LEN) ++ newIndex = newLen - CRC_LEN; + newName[newIndex++] = CRC_MARK; + valueCRC = crc_itu_t(0, fidName, fidNameLen); + newName[newIndex++] = hex_asc_upper_hi(valueCRC >> 8); diff --git a/queue-3.17/udf-verify-i_size-when-loading-inode.patch b/queue-3.17/udf-verify-i_size-when-loading-inode.patch new file mode 100644 index 00000000000..1235e8346d3 --- /dev/null +++ b/queue-3.17/udf-verify-i_size-when-loading-inode.patch @@ -0,0 +1,44 @@ +From e159332b9af4b04d882dbcfe1bb0117f0a6d4b58 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 19 Dec 2014 12:03:53 +0100 +Subject: udf: Verify i_size when loading inode + +From: Jan Kara + +commit e159332b9af4b04d882dbcfe1bb0117f0a6d4b58 upstream. + +Verify that inode size is sane when loading inode with data stored in +ICB. Otherwise we may get confused later when working with the inode and +inode size is too big. + +Reported-by: Carl Henrik Lunde +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/inode.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -1489,6 +1489,20 @@ reread: + } + inode->i_generation = iinfo->i_unique; + ++ /* Sanity checks for files in ICB so that we don't get confused later */ ++ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { ++ /* ++ * For file in ICB data is stored in allocation descriptor ++ * so sizes should match ++ */ ++ if (iinfo->i_lenAlloc != inode->i_size) ++ goto out; ++ /* File in ICB has to fit in there... */ ++ if (inode->i_size > inode->i_sb->s_blocksize - ++ udf_file_entry_alloc_offset(inode)) ++ goto out; ++ } ++ + switch (fe->icbTag.fileType) { + case ICBTAG_FILE_TYPE_DIRECTORY: + inode->i_op = &udf_dir_inode_operations; diff --git a/queue-3.17/udf-verify-symlink-size-before-loading-it.patch b/queue-3.17/udf-verify-symlink-size-before-loading-it.patch new file mode 100644 index 00000000000..483ed63907a --- /dev/null +++ b/queue-3.17/udf-verify-symlink-size-before-loading-it.patch @@ -0,0 +1,67 @@ +From a1d47b262952a45aae62bd49cfaf33dd76c11a2c Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 19 Dec 2014 12:21:47 +0100 +Subject: udf: Verify symlink size before loading it + +From: Jan Kara + +commit a1d47b262952a45aae62bd49cfaf33dd76c11a2c upstream. + +UDF specification allows arbitrarily large symlinks. However we support +only symlinks at most one block large. Check the length of the symlink +so that we don't access memory beyond end of the symlink block. + +Reported-by: Carl Henrik Lunde +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/symlink.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -99,11 +99,17 @@ static int udf_symlink_filler(struct fil + struct inode *inode = page->mapping->host; + struct buffer_head *bh = NULL; + unsigned char *symlink; +- int err = -EIO; ++ int err; + unsigned char *p = kmap(page); + struct udf_inode_info *iinfo; + uint32_t pos; + ++ /* We don't support symlinks longer than one block */ ++ if (inode->i_size > inode->i_sb->s_blocksize) { ++ err = -ENAMETOOLONG; ++ goto out_unmap; ++ } ++ + iinfo = UDF_I(inode); + pos = udf_block_map(inode, 0); + +@@ -113,8 +119,10 @@ static int udf_symlink_filler(struct fil + } else { + bh = sb_bread(inode->i_sb, pos); + +- if (!bh) +- goto out; ++ if (!bh) { ++ err = -EIO; ++ goto out_unlock_inode; ++ } + + symlink = bh->b_data; + } +@@ -130,9 +138,10 @@ static int udf_symlink_filler(struct fil + unlock_page(page); + return 0; + +-out: ++out_unlock_inode: + up_read(&iinfo->i_data_sem); + SetPageError(page); ++out_unmap: + kunmap(page); + unlock_page(page); + return err;