]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Jan 2015 01:38:45 +0000 (17:38 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Jan 2015 01:38:45 +0000 (17:38 -0800)
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-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
mm-cma-fix-boot-regression-due-to-physical-address-of-high_memory.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

19 files changed:
queue-3.18/audit-don-t-attempt-to-lookup-pids-when-changing-pid-filtering-audit-rules.patch [new file with mode: 0644]
queue-3.18/audit-restore-audit_loginuid-unset-abi.patch [new file with mode: 0644]
queue-3.18/audit-use-supplied-gfp_mask-from-audit_buffer-in-kauditd_send_multicast_skb.patch [new file with mode: 0644]
queue-3.18/btrfs-do-not-move-em-to-modified-list-when-unpinning.patch [new file with mode: 0644]
queue-3.18/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch [new file with mode: 0644]
queue-3.18/btrfs-fix-wrong-accounting-of-raid1-data-profile-in-statfs.patch [new file with mode: 0644]
queue-3.18/btrfs-make-sure-logged-extents-complete-in-the-current-transaction-v3.patch [new file with mode: 0644]
queue-3.18/btrfs-make-sure-we-wait-on-logged-extents-when-fsycning-two-subvols.patch [new file with mode: 0644]
queue-3.18/crypto-af_alg-fix-backlog-handling.patch [new file with mode: 0644]
queue-3.18/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch [new file with mode: 0644]
queue-3.18/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch [new file with mode: 0644]
queue-3.18/exit-pidns-alloc_pid-leaks-pid_namespace-if-child_reaper-is-exiting.patch [new file with mode: 0644]
queue-3.18/mm-cma-fix-boot-regression-due-to-physical-address-of-high_memory.patch [new file with mode: 0644]
queue-3.18/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch [new file with mode: 0644]
queue-3.18/series
queue-3.18/udf-check-component-length-before-reading-it.patch [new file with mode: 0644]
queue-3.18/udf-check-path-length-when-reading-symlink.patch [new file with mode: 0644]
queue-3.18/udf-verify-i_size-when-loading-inode.patch [new file with mode: 0644]
queue-3.18/udf-verify-symlink-size-before-loading-it.patch [new file with mode: 0644]

diff --git a/queue-3.18/audit-don-t-attempt-to-lookup-pids-when-changing-pid-filtering-audit-rules.patch b/queue-3.18/audit-don-t-attempt-to-lookup-pids-when-changing-pid-filtering-audit-rules.patch
new file mode 100644 (file)
index 0000000..ea06c94
--- /dev/null
@@ -0,0 +1,57 @@
+From 3640dcfa4fd00cd91d88bb86250bdb496f7070c0 Mon Sep 17 00:00:00 2001
+From: Paul Moore <pmoore@redhat.com>
+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 <pmoore@redhat.com>
+
+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 <rgb@redhat.com>
+Signed-off-by: Paul Moore <pmoore@redhat.com>
+Acked-by: Eric Paris <eparis@redhat.com>
+Reviewed-by: Richard Guy Briggs <rgb@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/auditfilter.c |   13 -------------
+ 1 file changed, 13 deletions(-)
+
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -444,19 +444,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.18/audit-restore-audit_loginuid-unset-abi.patch b/queue-3.18/audit-restore-audit_loginuid-unset-abi.patch
new file mode 100644 (file)
index 0000000..a0d1755
--- /dev/null
@@ -0,0 +1,100 @@
+From 041d7b98ffe59c59fdd639931dea7d74f9aa9a59 Mon Sep 17 00:00:00 2001
+From: Richard Guy Briggs <rgb@redhat.com>
+Date: Tue, 23 Dec 2014 13:02:04 -0500
+Subject: audit: restore AUDIT_LOGINUID unset ABI
+
+From: Richard Guy Briggs <rgb@redhat.com>
+
+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 <rgb@redhat.com>
+Signed-off-by: Paul Moore <pmoore@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
+       union {
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -442,6 +442,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);
+@@ -617,6 +618,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;
+               }
+@@ -633,6 +641,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)
+@@ -751,6 +760,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.18/audit-use-supplied-gfp_mask-from-audit_buffer-in-kauditd_send_multicast_skb.patch b/queue-3.18/audit-use-supplied-gfp_mask-from-audit_buffer-in-kauditd_send_multicast_skb.patch
new file mode 100644 (file)
index 0000000..2b77a0a
--- /dev/null
@@ -0,0 +1,94 @@
+From 54dc77d974a50147d6639dac6f59cb2c29207161 Mon Sep 17 00:00:00 2001
+From: Richard Guy Briggs <rgb@redhat.com>
+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 <rgb@redhat.com>
+
+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: [<ffffffff91152e30>] prepare_bprm_creds+0x28/0x8b
+  #1:  (tty_files_lock){+.+.+.}, at: [<ffffffff9123e787>] 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:
+  [<ffffffff916ba529>] dump_stack+0x50/0xa8
+  [<ffffffff91063185>] ___might_sleep+0x1b6/0x1be
+  [<ffffffff910632a6>] __might_sleep+0x119/0x128
+  [<ffffffff91140720>] cache_alloc_debugcheck_before.isra.45+0x1d/0x1f
+  [<ffffffff91141d81>] kmem_cache_alloc+0x43/0x1c9
+  [<ffffffff914e148d>] __alloc_skb+0x42/0x1a3
+  [<ffffffff914e2b62>] skb_copy+0x3e/0xa3
+  [<ffffffff910c263e>] audit_log_end+0x83/0x100
+  [<ffffffff9123b8d3>] ? avc_audit_pre_callback+0x103/0x103
+  [<ffffffff91252a73>] common_lsm_audit+0x441/0x450
+  [<ffffffff9123c163>] slow_avc_audit+0x63/0x67
+  [<ffffffff9123c42c>] avc_has_perm+0xca/0xe3
+  [<ffffffff9123dc2d>] inode_has_perm+0x5a/0x65
+  [<ffffffff9123e7ca>] selinux_bprm_committing_creds+0x98/0x22b
+  [<ffffffff91239e64>] security_bprm_committing_creds+0xe/0x10
+  [<ffffffff911515e6>] install_exec_creds+0xe/0x79
+  [<ffffffff911974cf>] load_elf_binary+0xe36/0x10d7
+  [<ffffffff9115198e>] search_binary_handler+0x81/0x18c
+  [<ffffffff91153376>] do_execveat_common.isra.31+0x4e3/0x7b7
+  [<ffffffff91153669>] do_execve+0x1f/0x21
+  [<ffffffff91153967>] SyS_execve+0x25/0x29
+  [<ffffffff916c61a9>] stub_execve+0x69/0xa0
+
+Reported-by: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
+Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
+Tested-by: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
+Signed-off-by: Paul Moore <pmoore@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
+ }
+ /*
+@@ -1949,7 +1949,7 @@ void audit_log_end(struct audit_buffer *
+               struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
+               nlh->nlmsg_len = ab->skb->len;
+-              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.18/btrfs-do-not-move-em-to-modified-list-when-unpinning.patch b/queue-3.18/btrfs-do-not-move-em-to-modified-list-when-unpinning.patch
new file mode 100644 (file)
index 0000000..15665f4
--- /dev/null
@@ -0,0 +1,55 @@
+From a28046956c71985046474283fa3bcd256915fb72 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Fri, 14 Nov 2014 16:16:30 -0500
+Subject: Btrfs: do not move em to modified list when unpinning
+
+From: Josef Bacik <jbacik@fb.com>
+
+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 <jbacik@fb.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.18/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch b/queue-3.18/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch
new file mode 100644 (file)
index 0000000..5ad6e05
--- /dev/null
@@ -0,0 +1,172 @@
+From 678886bdc6378c1cbd5072da2c5a3035000214e3 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Sun, 7 Dec 2014 21:31:47 +0000
+Subject: Btrfs: fix fs corruption on transaction abort if device supports discard
+
+From: Filipe Manana <fdmanana@suse.com>
+
+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]  [<ffffffff8140c7b6>] dump_stack+0x4d/0x66
+      [112065.254271]  [<ffffffff81042984>] warn_slowpath_common+0x7f/0x98
+      [112065.254567]  [<ffffffffa0325990>] ? __btrfs_abort_transaction+0x50/0x10b [btrfs]
+      [112065.261674]  [<ffffffff810429e5>] warn_slowpath_fmt+0x48/0x50
+      [112065.261922]  [<ffffffffa032949e>] ? btrfs_free_path+0x26/0x29 [btrfs]
+      [112065.262211]  [<ffffffffa0325990>] __btrfs_abort_transaction+0x50/0x10b [btrfs]
+      [112065.262545]  [<ffffffffa036b1d6>] btrfs_remove_chunk+0x537/0x58b [btrfs]
+      [112065.262771]  [<ffffffffa033840f>] btrfs_delete_unused_bgs+0x1de/0x21b [btrfs]
+      [112065.263105]  [<ffffffffa0343106>] 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 <fdmanana@suse.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -4106,12 +4106,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();
+       }
+@@ -9585,7 +9587,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.18/btrfs-fix-wrong-accounting-of-raid1-data-profile-in-statfs.patch b/queue-3.18/btrfs-fix-wrong-accounting-of-raid1-data-profile-in-statfs.patch
new file mode 100644 (file)
index 0000000..a7d26d2
--- /dev/null
@@ -0,0 +1,34 @@
+From 0d95c1bec906dd1ad951c9c001e798ca52baeb0f Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.cz>
+Date: Fri, 14 Nov 2014 15:05:06 +0100
+Subject: btrfs: fix wrong accounting of raid1 data profile in statfs
+
+From: David Sterba <dsterba@suse.cz>
+
+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 <Martin@lichtvoll.de>
+Fixes: ba7b6e62f420 ("btrfs: adjust statfs calculations according to raid profiles")
+Signed-off-by: David Sterba <dsterba@suse.cz>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/super.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/super.c
++++ b/fs/btrfs/super.c
+@@ -1824,7 +1824,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.18/btrfs-make-sure-logged-extents-complete-in-the-current-transaction-v3.patch b/queue-3.18/btrfs-make-sure-logged-extents-complete-in-the-current-transaction-v3.patch
new file mode 100644 (file)
index 0000000..771bea5
--- /dev/null
@@ -0,0 +1,273 @@
+From 50d9aa99bd35c77200e0e3dd7a72274f8304701f Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Fri, 21 Nov 2014 14:52:38 -0500
+Subject: Btrfs: make sure logged extents complete in the current transaction V3
+
+From: Josef Bacik <jbacik@fb.com>
+
+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 <jbacik@fb.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -4129,6 +4129,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)
+ {
+@@ -4140,6 +4159,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 =
+@@ -1652,6 +1660,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)
+ {
+@@ -1702,6 +1732,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);
+@@ -1754,6 +1785,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
+@@ -2600,7 +2600,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);
+@@ -2645,7 +2645,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);
+@@ -3766,7 +3766,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))
+               btrfs_set_token_file_extent_type(leaf, fi,
diff --git a/queue-3.18/btrfs-make-sure-we-wait-on-logged-extents-when-fsycning-two-subvols.patch b/queue-3.18/btrfs-make-sure-we-wait-on-logged-extents-when-fsycning-two-subvols.patch
new file mode 100644 (file)
index 0000000..50e9340
--- /dev/null
@@ -0,0 +1,37 @@
+From 9dba8cf128ef98257ca719722280c9634e7e9dc7 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+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 <jbacik@fb.com>
+
+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 <jbacik@fb.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -2600,9 +2600,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.18/crypto-af_alg-fix-backlog-handling.patch b/queue-3.18/crypto-af_alg-fix-backlog-handling.patch
new file mode 100644 (file)
index 0000000..67ba40d
--- /dev/null
@@ -0,0 +1,48 @@
+From 7e77bdebff5cb1e9876c561f69710b9ab8fa1f7e Mon Sep 17 00:00:00 2001
+From: Rabin Vincent <rabin.vincent@axis.com>
+Date: Fri, 19 Dec 2014 13:36:08 +0100
+Subject: crypto: af_alg - fix backlog handling
+
+From: Rabin Vincent <rabin.vincent@axis.com>
+
+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 <rabin.vincent@axis.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.18/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch b/queue-3.18/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch
new file mode 100644 (file)
index 0000000..e76a8f1
--- /dev/null
@@ -0,0 +1,103 @@
+From 332b122d39c9cbff8b799007a825d94b2e7c12f2 Mon Sep 17 00:00:00 2001
+From: Tyler Hicks <tyhicks@canonical.com>
+Date: Tue, 7 Oct 2014 15:51:55 -0500
+Subject: eCryptfs: Force RO mount when encrypted view is enabled
+
+From: Tyler Hicks <tyhicks@canonical.com>
+
+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 <tyhicks@canonical.com>
+Reported-by: Priya Bansal <p.bansal@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.18/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch b/queue-3.18/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch
new file mode 100644 (file)
index 0000000..64b4ea9
--- /dev/null
@@ -0,0 +1,34 @@
+From 942080643bce061c3dd9d5718d3b745dcb39a8bc Mon Sep 17 00:00:00 2001
+From: Michael Halcrow <mhalcrow@google.com>
+Date: Wed, 26 Nov 2014 09:09:16 -0800
+Subject: eCryptfs: Remove buggy and unnecessary write in file name decode routine
+
+From: Michael Halcrow <mhalcrow@google.com>
+
+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 <mhalcrow@google.com>
+Reported-by: Dmitry Chernenkov <dmitryc@google.com>
+Suggested-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.18/exit-pidns-alloc_pid-leaks-pid_namespace-if-child_reaper-is-exiting.patch b/queue-3.18/exit-pidns-alloc_pid-leaks-pid_namespace-if-child_reaper-is-exiting.patch
new file mode 100644 (file)
index 0000000..ad23c05
--- /dev/null
@@ -0,0 +1,41 @@
+From 24c037ebf5723d4d9ab0996433cee4f96c292a4d Mon Sep 17 00:00:00 2001
+From: Oleg Nesterov <oleg@redhat.com>
+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 <oleg@redhat.com>
+
+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 <oleg@redhat.com>
+Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Aaron Tomlin <atomlin@redhat.com>
+Cc: Pavel Emelyanov <xemul@parallels.com>
+Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
+Cc: Sterling Alexander <stalexan@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.18/mm-cma-fix-boot-regression-due-to-physical-address-of-high_memory.patch b/queue-3.18/mm-cma-fix-boot-regression-due-to-physical-address-of-high_memory.patch
new file mode 100644 (file)
index 0000000..82bf667
--- /dev/null
@@ -0,0 +1,72 @@
+From 6b101e2a3ce4d2a0312087598bd1ab4a1db2ac40 Mon Sep 17 00:00:00 2001
+From: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+Date: Wed, 10 Dec 2014 15:41:12 -0800
+Subject: mm/CMA: fix boot regression due to physical address of high_memory
+
+From: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+
+commit 6b101e2a3ce4d2a0312087598bd1ab4a1db2ac40 upstream.
+
+high_memory isn't direct mapped memory so retrieving it's physical address
+isn't appropriate.  But, it would be useful to check physical address of
+highmem boundary so it's justfiable to get physical address from it.  In
+x86, there is a validation check if CONFIG_DEBUG_VIRTUAL and it triggers
+following boot failure reported by Ingo.
+
+  ...
+  BUG: Int 6: CR2 00f06f53
+  ...
+  Call Trace:
+    dump_stack+0x41/0x52
+    early_idt_handler+0x6b/0x6b
+    cma_declare_contiguous+0x33/0x212
+    dma_contiguous_reserve_area+0x31/0x4e
+    dma_contiguous_reserve+0x11d/0x125
+    setup_arch+0x7b5/0xb63
+    start_kernel+0xb8/0x3e6
+    i386_start_kernel+0x79/0x7d
+
+To fix boot regression, this patch implements workaround to avoid
+validation check in x86 when retrieving physical address of high_memory.
+__pa_nodebug() used by this patch is implemented only in x86 so there is
+no choice but to use dirty #ifdef.
+
+[akpm@linux-foundation.org: tweak comment]
+Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+Reported-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Ingo Molnar <mingo@kernel.org>
+Cc: Marek Szyprowski <m.szyprowski@samsung.com>
+Cc: Russell King <rmk@arm.linux.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/cma.c |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/mm/cma.c
++++ b/mm/cma.c
+@@ -215,9 +215,21 @@ int __init cma_declare_contiguous(phys_a
+                       bool fixed, struct cma **res_cma)
+ {
+       phys_addr_t memblock_end = memblock_end_of_DRAM();
+-      phys_addr_t highmem_start = __pa(high_memory);
++      phys_addr_t highmem_start;
+       int ret = 0;
++#ifdef CONFIG_X86
++      /*
++       * high_memory isn't direct mapped memory so retrieving its physical
++       * address isn't appropriate.  But it would be useful to check the
++       * physical address of the highmem boundary so it's justfiable to get
++       * the physical address from it.  On x86 there is a validation check for
++       * this case, so the following workaround is needed to avoid it.
++       */
++      highmem_start = __pa_nodebug(high_memory);
++#else
++      highmem_start = __pa(high_memory);
++#endif
+       pr_debug("%s(size %pa, base %pa, limit %pa alignment %pa)\n",
+               __func__, &size, &base, &limit, &alignment);
diff --git a/queue-3.18/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch b/queue-3.18/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch
new file mode 100644 (file)
index 0000000..2dd9140
--- /dev/null
@@ -0,0 +1,39 @@
+From a682e9c28cac152e6e54c39efcf046e0c8cfcf63 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Wed, 10 Dec 2014 15:52:22 -0800
+Subject: ncpfs: return proper error from NCP_IOC_SETROOT ioctl
+
+From: Jan Kara <jack@suse.cz>
+
+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 <jack@suse.cz>
+Cc: Petr Vandrovec <petr@vandrovec.name>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
index 05645a40a2be84673b0dda7b1585ae469993d96a..6bc6815a8d10906ce71daa3f9f16a4f2f91e2bcf 100644 (file)
@@ -64,3 +64,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
+mm-cma-fix-boot-regression-due-to-physical-address-of-high_memory.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-fs-corruption-on-transaction-abort-if-device-supports-discard.patch
diff --git a/queue-3.18/udf-check-component-length-before-reading-it.patch b/queue-3.18/udf-check-component-length-before-reading-it.patch
new file mode 100644 (file)
index 0000000..157bfec
--- /dev/null
@@ -0,0 +1,61 @@
+From e237ec37ec154564f8690c5bd1795339955eeef9 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 19 Dec 2014 14:27:55 +0100
+Subject: udf: Check component length before reading it
+
+From: Jan Kara <jack@suse.cz>
+
+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 <chlunde@ping.uio.no>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.18/udf-check-path-length-when-reading-symlink.patch b/queue-3.18/udf-check-path-length-when-reading-symlink.patch
new file mode 100644 (file)
index 0000000..915ef3c
--- /dev/null
@@ -0,0 +1,228 @@
+From 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 18 Dec 2014 22:37:50 +0100
+Subject: udf: Check path length when reading symlink
+
+From: Jan Kara <jack@suse.cz>
+
+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 <chlunde@ping.uio.no>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 <linux/buffer_head.h>
+ #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.18/udf-verify-i_size-when-loading-inode.patch b/queue-3.18/udf-verify-i_size-when-loading-inode.patch
new file mode 100644 (file)
index 0000000..1235e83
--- /dev/null
@@ -0,0 +1,44 @@
+From e159332b9af4b04d882dbcfe1bb0117f0a6d4b58 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 19 Dec 2014 12:03:53 +0100
+Subject: udf: Verify i_size when loading inode
+
+From: Jan Kara <jack@suse.cz>
+
+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 <chlunde@ping.uio.no>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.18/udf-verify-symlink-size-before-loading-it.patch b/queue-3.18/udf-verify-symlink-size-before-loading-it.patch
new file mode 100644 (file)
index 0000000..483ed63
--- /dev/null
@@ -0,0 +1,67 @@
+From a1d47b262952a45aae62bd49cfaf33dd76c11a2c Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 19 Dec 2014 12:21:47 +0100
+Subject: udf: Verify symlink size before loading it
+
+From: Jan Kara <jack@suse.cz>
+
+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 <chlunde@gmail.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;