namei: get rid of nameidata->base
[firefly-linux-kernel-4.4.55.git] / fs / ext4 / ioctl.c
index f58a0d106726100262aad4557fc91dd46f76ddf4..2cb9e178d1c557f62c35d1d0f7bd0d911665738a 100644 (file)
@@ -8,12 +8,12 @@
  */
 
 #include <linux/fs.h>
-#include <linux/jbd2.h>
 #include <linux/capability.h>
 #include <linux/time.h>
 #include <linux/compat.h>
 #include <linux/mount.h>
 #include <linux/file.h>
+#include <linux/random.h>
 #include <asm/uaccess.h>
 #include "ext4_jbd2.h"
 #include "ext4.h"
@@ -196,6 +196,16 @@ journal_err_out:
        return err;
 }
 
+static int uuid_is_zero(__u8 u[16])
+{
+       int     i;
+
+       for (i = 0; i < 16; i++)
+               if (u[i])
+                       return 0;
+       return 1;
+}
+
 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
@@ -615,7 +625,78 @@ resizefs_out:
        }
        case EXT4_IOC_PRECACHE_EXTENTS:
                return ext4_ext_precache(inode);
+       case EXT4_IOC_SET_ENCRYPTION_POLICY: {
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
+               struct ext4_encryption_policy policy;
+               int err = 0;
+
+               if (copy_from_user(&policy,
+                                  (struct ext4_encryption_policy __user *)arg,
+                                  sizeof(policy))) {
+                       err = -EFAULT;
+                       goto encryption_policy_out;
+               }
 
+               err = ext4_process_policy(&policy, inode);
+encryption_policy_out:
+               return err;
+#else
+               return -EOPNOTSUPP;
+#endif
+       }
+       case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
+               int err, err2;
+               struct ext4_sb_info *sbi = EXT4_SB(sb);
+               handle_t *handle;
+
+               if (!ext4_sb_has_crypto(sb))
+                       return -EOPNOTSUPP;
+               if (uuid_is_zero(sbi->s_es->s_encrypt_pw_salt)) {
+                       err = mnt_want_write_file(filp);
+                       if (err)
+                               return err;
+                       handle = ext4_journal_start_sb(sb, EXT4_HT_MISC, 1);
+                       if (IS_ERR(handle)) {
+                               err = PTR_ERR(handle);
+                               goto pwsalt_err_exit;
+                       }
+                       err = ext4_journal_get_write_access(handle, sbi->s_sbh);
+                       if (err)
+                               goto pwsalt_err_journal;
+                       generate_random_uuid(sbi->s_es->s_encrypt_pw_salt);
+                       err = ext4_handle_dirty_metadata(handle, NULL,
+                                                        sbi->s_sbh);
+               pwsalt_err_journal:
+                       err2 = ext4_journal_stop(handle);
+                       if (err2 && !err)
+                               err = err2;
+               pwsalt_err_exit:
+                       mnt_drop_write_file(filp);
+                       if (err)
+                               return err;
+               }
+               if (copy_to_user((void *) arg, sbi->s_es->s_encrypt_pw_salt,
+                                16))
+                       return -EFAULT;
+               return 0;
+       }
+       case EXT4_IOC_GET_ENCRYPTION_POLICY: {
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
+               struct ext4_encryption_policy policy;
+               int err = 0;
+
+               if (!ext4_encrypted_inode(inode))
+                       return -ENOENT;
+               err = ext4_get_policy(inode, &policy);
+               if (err)
+                       return err;
+               if (copy_to_user((void *)arg, &policy, sizeof(policy)))
+                       return -EFAULT;
+               return 0;
+#else
+               return -EOPNOTSUPP;
+#endif
+       }
        default:
                return -ENOTTY;
        }
@@ -680,6 +761,9 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case FITRIM:
        case EXT4_IOC_RESIZE_FS:
        case EXT4_IOC_PRECACHE_EXTENTS:
+       case EXT4_IOC_SET_ENCRYPTION_POLICY:
+       case EXT4_IOC_GET_ENCRYPTION_PWSALT:
+       case EXT4_IOC_GET_ENCRYPTION_POLICY:
                break;
        default:
                return -ENOIOCTLCMD;