]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 1 Nov 2020 10:32:46 +0000 (11:32 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 1 Nov 2020 10:32:46 +0000 (11:32 +0100)
added patches:
fscrypt-return-exdev-for-incompatible-rename-or-link-into-encrypted-dir.patch
fscrypt-use-eexist-when-file-already-uses-different-policy.patch
fscrypto-move-ioctl-processing-more-fully-into-common-code.patch

queue-4.9/fscrypt-return-exdev-for-incompatible-rename-or-link-into-encrypted-dir.patch [new file with mode: 0644]
queue-4.9/fscrypt-use-eexist-when-file-already-uses-different-policy.patch [new file with mode: 0644]
queue-4.9/fscrypto-move-ioctl-processing-more-fully-into-common-code.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/fscrypt-return-exdev-for-incompatible-rename-or-link-into-encrypted-dir.patch b/queue-4.9/fscrypt-return-exdev-for-incompatible-rename-or-link-into-encrypted-dir.patch
new file mode 100644 (file)
index 0000000..007b9b0
--- /dev/null
@@ -0,0 +1,136 @@
+From f5e55e777cc93eae1416f0fa4908e8846b6d7825 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Tue, 22 Jan 2019 16:20:21 -0800
+Subject: fscrypt: return -EXDEV for incompatible rename or link into encrypted dir
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit f5e55e777cc93eae1416f0fa4908e8846b6d7825 upstream.
+
+Currently, trying to rename or link a regular file, directory, or
+symlink into an encrypted directory fails with EPERM when the source
+file is unencrypted or is encrypted with a different encryption policy,
+and is on the same mountpoint.  It is correct for the operation to fail,
+but the choice of EPERM breaks tools like 'mv' that know to copy rather
+than rename if they see EXDEV, but don't know what to do with EPERM.
+
+Our original motivation for EPERM was to encourage users to securely
+handle their data.  Encrypting files by "moving" them into an encrypted
+directory can be insecure because the unencrypted data may remain in
+free space on disk, where it can later be recovered by an attacker.
+It's much better to encrypt the data from the start, or at least try to
+securely delete the source data e.g. using the 'shred' program.
+
+However, the current behavior hasn't been effective at achieving its
+goal because users tend to be confused, hack around it, and complain;
+see e.g. https://github.com/google/fscrypt/issues/76.  And in some cases
+it's actually inconsistent or unnecessary.  For example, 'mv'-ing files
+between differently encrypted directories doesn't work even in cases
+where it can be secure, such as when in userspace the same passphrase
+protects both directories.  Yet, you *can* already 'mv' unencrypted
+files into an encrypted directory if the source files are on a different
+mountpoint, even though doing so is often insecure.
+
+There are probably better ways to teach users to securely handle their
+files.  For example, the 'fscrypt' userspace tool could provide a
+command that migrates unencrypted files into an encrypted directory,
+acting like 'shred' on the source files and providing appropriate
+warnings depending on the type of the source filesystem and disk.
+
+Receiving errors on unimportant files might also force some users to
+disable encryption, thus making the behavior counterproductive.  It's
+desirable to make encryption as unobtrusive as possible.
+
+Therefore, change the error code from EPERM to EXDEV so that tools
+looking for EXDEV will fall back to a copy.
+
+This, of course, doesn't prevent users from still doing the right things
+to securely manage their files.  Note that this also matches the
+behavior when a file is renamed between two project quota hierarchies;
+so there's precedent for using EXDEV for things other than mountpoints.
+
+xfstests generic/398 will require an update with this change.
+
+[Rewritten from an earlier patch series by Michael Halcrow.]
+
+Cc: Michael Halcrow <mhalcrow@google.com>
+Cc: Joe Richey <joerichey@google.com>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/crypto/policy.c |    3 +--
+ fs/ext4/namei.c    |    6 +++---
+ fs/f2fs/namei.c    |    6 +++---
+ 3 files changed, 7 insertions(+), 8 deletions(-)
+
+--- a/fs/crypto/policy.c
++++ b/fs/crypto/policy.c
+@@ -180,8 +180,7 @@ EXPORT_SYMBOL(fscrypt_get_policy);
+  * malicious offline violations of this constraint, while the link and rename
+  * checks are needed to prevent online violations of this constraint.
+  *
+- * Return: 1 if permitted, 0 if forbidden.  If forbidden, the caller must fail
+- * the filesystem operation with EPERM.
++ * Return: 1 if permitted, 0 if forbidden.
+  */
+ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
+ {
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3259,7 +3259,7 @@ static int ext4_link(struct dentry *old_
+               return -EMLINK;
+       if (ext4_encrypted_inode(dir) &&
+                       !fscrypt_has_permitted_context(dir, inode))
+-              return -EPERM;
++              return -EXDEV;
+        if ((ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT)) &&
+          (!projid_eq(EXT4_I(dir)->i_projid,
+@@ -3597,7 +3597,7 @@ static int ext4_rename(struct inode *old
+       if ((old.dir != new.dir) &&
+           ext4_encrypted_inode(new.dir) &&
+           !fscrypt_has_permitted_context(new.dir, old.inode)) {
+-              retval = -EPERM;
++              retval = -EXDEV;
+               goto end_rename;
+       }
+@@ -3776,7 +3776,7 @@ static int ext4_cross_rename(struct inod
+           (old_dir != new_dir) &&
+           (!fscrypt_has_permitted_context(new_dir, old.inode) ||
+            !fscrypt_has_permitted_context(old_dir, new.inode)))
+-              return -EPERM;
++              return -EXDEV;
+       if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT) &&
+            !projid_eq(EXT4_I(new_dir)->i_projid,
+--- a/fs/f2fs/namei.c
++++ b/fs/f2fs/namei.c
+@@ -177,7 +177,7 @@ static int f2fs_link(struct dentry *old_
+       if (f2fs_encrypted_inode(dir) &&
+                       !fscrypt_has_permitted_context(dir, inode))
+-              return -EPERM;
++              return -EXDEV;
+       f2fs_balance_fs(sbi, true);
+@@ -667,7 +667,7 @@ static int f2fs_rename(struct inode *old
+       if ((old_dir != new_dir) && f2fs_encrypted_inode(new_dir) &&
+                       !fscrypt_has_permitted_context(new_dir, old_inode)) {
+-              err = -EPERM;
++              err = -EXDEV;
+               goto out;
+       }
+@@ -855,7 +855,7 @@ static int f2fs_cross_rename(struct inod
+                       (old_dir != new_dir) &&
+                       (!fscrypt_has_permitted_context(new_dir, old_inode) ||
+                        !fscrypt_has_permitted_context(old_dir, new_inode)))
+-              return -EPERM;
++              return -EXDEV;
+       old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
+       if (!old_entry) {
diff --git a/queue-4.9/fscrypt-use-eexist-when-file-already-uses-different-policy.patch b/queue-4.9/fscrypt-use-eexist-when-file-already-uses-different-policy.patch
new file mode 100644 (file)
index 0000000..415c8d6
--- /dev/null
@@ -0,0 +1,39 @@
+From 8488cd96ff88966ccb076e4f3654f59d84ba686d Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 5 Dec 2016 11:12:46 -0800
+Subject: fscrypt: use EEXIST when file already uses different policy
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 8488cd96ff88966ccb076e4f3654f59d84ba686d upstream.
+
+As part of an effort to clean up fscrypt-related error codes, make
+FS_IOC_SET_ENCRYPTION_POLICY fail with EEXIST when the file already uses
+a different encryption policy.  This is more descriptive than EINVAL,
+which was ambiguous with some of the other error cases.
+
+I am not aware of any users who might be relying on the previous error
+code of EINVAL, which was never documented anywhere.
+
+This failure case will be exercised by an xfstest.
+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ fs/crypto/policy.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/crypto/policy.c
++++ b/fs/crypto/policy.c
+@@ -131,7 +131,7 @@ int fscrypt_ioctl_set_policy(struct file
+               printk(KERN_WARNING
+                      "%s: Policy inconsistent with encryption context\n",
+                      __func__);
+-              ret = -EINVAL;
++              ret = -EEXIST;
+       }
+       inode_unlock(inode);
diff --git a/queue-4.9/fscrypto-move-ioctl-processing-more-fully-into-common-code.patch b/queue-4.9/fscrypto-move-ioctl-processing-more-fully-into-common-code.patch
new file mode 100644 (file)
index 0000000..07a2947
--- /dev/null
@@ -0,0 +1,255 @@
+From db717d8e26c2d1b0dba3e08668a1e6a7f665adde Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Sat, 26 Nov 2016 19:07:49 -0500
+Subject: fscrypto: move ioctl processing more fully into common code
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit db717d8e26c2d1b0dba3e08668a1e6a7f665adde upstream.
+
+Multiple bugs were recently fixed in the "set encryption policy" ioctl.
+To make it clear that fscrypt_process_policy() and fscrypt_get_policy()
+implement ioctls and therefore their implementations must take standard
+security and correctness precautions, rename them to
+fscrypt_ioctl_set_policy() and fscrypt_ioctl_get_policy().  Make the
+latter take in a struct file * to make it consistent with the former.
+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ fs/crypto/policy.c       |   34 +++++++++++++++++++++-------------
+ fs/ext4/ext4.h           |    4 ++--
+ fs/ext4/ioctl.c          |   32 ++++----------------------------
+ fs/f2fs/f2fs.h           |    4 ++--
+ fs/f2fs/file.c           |   19 ++-----------------
+ include/linux/fscrypto.h |   12 ++++++------
+ 6 files changed, 37 insertions(+), 68 deletions(-)
+
+--- a/fs/crypto/policy.c
++++ b/fs/crypto/policy.c
+@@ -93,16 +93,19 @@ static int create_encryption_context_fro
+       return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL);
+ }
+-int fscrypt_process_policy(struct file *filp,
+-                              const struct fscrypt_policy *policy)
++int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
+ {
++      struct fscrypt_policy policy;
+       struct inode *inode = file_inode(filp);
+       int ret;
++      if (copy_from_user(&policy, arg, sizeof(policy)))
++              return -EFAULT;
++
+       if (!inode_owner_or_capable(inode))
+               return -EACCES;
+-      if (policy->version != 0)
++      if (policy.version != 0)
+               return -EINVAL;
+       ret = mnt_want_write_file(filp);
+@@ -122,9 +125,9 @@ int fscrypt_process_policy(struct file *
+                       ret = -ENOTEMPTY;
+               else
+                       ret = create_encryption_context_from_policy(inode,
+-                                                                  policy);
++                                                                  &policy);
+       } else if (!is_encryption_context_consistent_with_policy(inode,
+-                                                               policy)) {
++                                                               &policy)) {
+               printk(KERN_WARNING
+                      "%s: Policy inconsistent with encryption context\n",
+                      __func__);
+@@ -136,11 +139,13 @@ int fscrypt_process_policy(struct file *
+       mnt_drop_write_file(filp);
+       return ret;
+ }
+-EXPORT_SYMBOL(fscrypt_process_policy);
++EXPORT_SYMBOL(fscrypt_ioctl_set_policy);
+-int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy)
++int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
+ {
++      struct inode *inode = file_inode(filp);
+       struct fscrypt_context ctx;
++      struct fscrypt_policy policy;
+       int res;
+       if (!inode->i_sb->s_cop->get_context ||
+@@ -153,15 +158,18 @@ int fscrypt_get_policy(struct inode *ino
+       if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1)
+               return -EINVAL;
+-      policy->version = 0;
+-      policy->contents_encryption_mode = ctx.contents_encryption_mode;
+-      policy->filenames_encryption_mode = ctx.filenames_encryption_mode;
+-      policy->flags = ctx.flags;
+-      memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor,
++      policy.version = 0;
++      policy.contents_encryption_mode = ctx.contents_encryption_mode;
++      policy.filenames_encryption_mode = ctx.filenames_encryption_mode;
++      policy.flags = ctx.flags;
++      memcpy(policy.master_key_descriptor, ctx.master_key_descriptor,
+                               FS_KEY_DESCRIPTOR_SIZE);
++
++      if (copy_to_user(arg, &policy, sizeof(policy)))
++              return -EFAULT;
+       return 0;
+ }
+-EXPORT_SYMBOL(fscrypt_get_policy);
++EXPORT_SYMBOL(fscrypt_ioctl_get_policy);
+ /**
+  * fscrypt_has_permitted_context() - is a file's encryption policy permitted
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2354,8 +2354,8 @@ static inline void ext4_fname_free_filen
+ #define fscrypt_pullback_bio_page     fscrypt_notsupp_pullback_bio_page
+ #define fscrypt_restore_control_page  fscrypt_notsupp_restore_control_page
+ #define fscrypt_zeroout_range         fscrypt_notsupp_zeroout_range
+-#define fscrypt_process_policy                fscrypt_notsupp_process_policy
+-#define fscrypt_get_policy            fscrypt_notsupp_get_policy
++#define fscrypt_ioctl_set_policy      fscrypt_notsupp_ioctl_set_policy
++#define fscrypt_ioctl_get_policy      fscrypt_notsupp_ioctl_get_policy
+ #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context
+ #define fscrypt_inherit_context               fscrypt_notsupp_inherit_context
+ #define fscrypt_get_encryption_info   fscrypt_notsupp_get_encryption_info
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -774,22 +774,12 @@ resizefs_out:
+       }
+       case EXT4_IOC_PRECACHE_EXTENTS:
+               return ext4_ext_precache(inode);
+-      case EXT4_IOC_SET_ENCRYPTION_POLICY: {
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-              struct fscrypt_policy policy;
++      case EXT4_IOC_SET_ENCRYPTION_POLICY:
+               if (!ext4_has_feature_encrypt(sb))
+                       return -EOPNOTSUPP;
++              return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
+-              if (copy_from_user(&policy,
+-                                 (struct fscrypt_policy __user *)arg,
+-                                 sizeof(policy)))
+-                      return -EFAULT;
+-              return fscrypt_process_policy(filp, &policy);
+-#else
+-              return -EOPNOTSUPP;
+-#endif
+-      }
+       case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
+               int err, err2;
+               struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -826,23 +816,9 @@ resizefs_out:
+                       return -EFAULT;
+               return 0;
+       }
+-      case EXT4_IOC_GET_ENCRYPTION_POLICY: {
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-              struct fscrypt_policy policy;
+-              int err = 0;
++      case EXT4_IOC_GET_ENCRYPTION_POLICY:
++              return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
+-              if (!ext4_encrypted_inode(inode))
+-                      return -ENOENT;
+-              err = fscrypt_get_policy(inode, &policy);
+-              if (err)
+-                      return err;
+-              if (copy_to_user((void __user *)arg, &policy, sizeof(policy)))
+-                      return -EFAULT;
+-              return 0;
+-#else
+-              return -EOPNOTSUPP;
+-#endif
+-      }
+       case EXT4_IOC_FSGETXATTR:
+       {
+               struct fsxattr fa;
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -2513,8 +2513,8 @@ static inline bool f2fs_may_encrypt(stru
+ #define fscrypt_pullback_bio_page     fscrypt_notsupp_pullback_bio_page
+ #define fscrypt_restore_control_page  fscrypt_notsupp_restore_control_page
+ #define fscrypt_zeroout_range         fscrypt_notsupp_zeroout_range
+-#define fscrypt_process_policy                fscrypt_notsupp_process_policy
+-#define fscrypt_get_policy            fscrypt_notsupp_get_policy
++#define fscrypt_ioctl_set_policy      fscrypt_notsupp_ioctl_set_policy
++#define fscrypt_ioctl_get_policy      fscrypt_notsupp_ioctl_get_policy
+ #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context
+ #define fscrypt_inherit_context               fscrypt_notsupp_inherit_context
+ #define fscrypt_get_encryption_info   fscrypt_notsupp_get_encryption_info
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1774,31 +1774,16 @@ static bool uuid_is_nonzero(__u8 u[16])
+ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
+ {
+-      struct fscrypt_policy policy;
+       struct inode *inode = file_inode(filp);
+-      if (copy_from_user(&policy, (struct fscrypt_policy __user *)arg,
+-                                                      sizeof(policy)))
+-              return -EFAULT;
+-
+       f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
+-      return fscrypt_process_policy(filp, &policy);
++      return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
+ }
+ static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg)
+ {
+-      struct fscrypt_policy policy;
+-      struct inode *inode = file_inode(filp);
+-      int err;
+-
+-      err = fscrypt_get_policy(inode, &policy);
+-      if (err)
+-              return err;
+-
+-      if (copy_to_user((struct fscrypt_policy __user *)arg, &policy, sizeof(policy)))
+-              return -EFAULT;
+-      return 0;
++      return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
+ }
+ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg)
+--- a/include/linux/fscrypto.h
++++ b/include/linux/fscrypto.h
+@@ -249,8 +249,8 @@ extern void fscrypt_restore_control_page
+ extern int fscrypt_zeroout_range(struct inode *, pgoff_t, sector_t,
+                                               unsigned int);
+ /* policy.c */
+-extern int fscrypt_process_policy(struct file *, const struct fscrypt_policy *);
+-extern int fscrypt_get_policy(struct inode *, struct fscrypt_policy *);
++extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
++extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
+ extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
+ extern int fscrypt_inherit_context(struct inode *, struct inode *,
+                                       void *, bool);
+@@ -318,14 +318,14 @@ static inline int fscrypt_notsupp_zeroou
+ }
+ /* policy.c */
+-static inline int fscrypt_notsupp_process_policy(struct file *f,
+-                              const struct fscrypt_policy *p)
++static inline int fscrypt_notsupp_ioctl_set_policy(struct file *f,
++                              const void __user *arg)
+ {
+       return -EOPNOTSUPP;
+ }
+-static inline int fscrypt_notsupp_get_policy(struct inode *i,
+-                              struct fscrypt_policy *p)
++static inline int fscrypt_notsupp_ioctl_get_policy(struct file *f,
++                              void __user *arg)
+ {
+       return -EOPNOTSUPP;
+ }
index 2cafdd82dda7c9a9cb43f1b026d65d7144efa360..9ac4b81bbaa8329b53f9fabc3286806e3477a1bd 100644 (file)
@@ -9,3 +9,6 @@ fuse-fix-page-dereference-after-free.patch
 p54-avoid-accessing-the-data-mapped-to-streaming-dma.patch
 mtd-lpddr-fix-bad-logic-in-print_drs_error.patch
 ata-sata_rcar-fix-dma-boundary-mask.patch
+fscrypt-return-exdev-for-incompatible-rename-or-link-into-encrypted-dir.patch
+fscrypto-move-ioctl-processing-more-fully-into-common-code.patch
+fscrypt-use-eexist-when-file-already-uses-different-policy.patch