Merge tag 'f2fs-for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
[linux-2.6-block.git] / fs / f2fs / file.c
index e4b78fb3fc79be7de9b72b960203ac24a6228bad..29bc0a542759a279f994862fe6eb3c8f97eac39d 100644 (file)
@@ -499,6 +499,10 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
 {
        int err = fscrypt_file_open(inode, filp);
 
+       if (err)
+               return err;
+
+       err = fsverity_file_open(inode, filp);
        if (err)
                return err;
 
@@ -747,15 +751,18 @@ static void __setattr_copy(struct inode *inode, const struct iattr *attr)
                inode->i_uid = attr->ia_uid;
        if (ia_valid & ATTR_GID)
                inode->i_gid = attr->ia_gid;
-       if (ia_valid & ATTR_ATIME)
-               inode->i_atime = timespec64_trunc(attr->ia_atime,
-                                                 inode->i_sb->s_time_gran);
-       if (ia_valid & ATTR_MTIME)
-               inode->i_mtime = timespec64_trunc(attr->ia_mtime,
-                                                 inode->i_sb->s_time_gran);
-       if (ia_valid & ATTR_CTIME)
-               inode->i_ctime = timespec64_trunc(attr->ia_ctime,
-                                                 inode->i_sb->s_time_gran);
+       if (ia_valid & ATTR_ATIME) {
+               inode->i_atime = timestamp_truncate(attr->ia_atime,
+                                                 inode);
+       }
+       if (ia_valid & ATTR_MTIME) {
+               inode->i_mtime = timestamp_truncate(attr->ia_mtime,
+                                                 inode);
+       }
+       if (ia_valid & ATTR_CTIME) {
+               inode->i_ctime = timestamp_truncate(attr->ia_ctime,
+                                                 inode);
+       }
        if (ia_valid & ATTR_MODE) {
                umode_t mode = attr->ia_mode;
 
@@ -784,6 +791,10 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
        if (err)
                return err;
 
+       err = fsverity_prepare_setattr(dentry, attr);
+       if (err)
+               return err;
+
        if (is_quota_modification(inode, attr)) {
                err = dquot_initialize(inode);
                if (err)
@@ -1722,6 +1733,7 @@ static const struct {
                FS_ENCRYPT_FL |         \
                FS_INLINE_DATA_FL |     \
                FS_NOCOW_FL |           \
+               FS_VERITY_FL |          \
                FS_CASEFOLD_FL)
 
 #define F2FS_SETTABLE_FS_FL (          \
@@ -1768,6 +1780,8 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
 
        if (IS_ENCRYPTED(inode))
                fsflags |= FS_ENCRYPT_FL;
+       if (IS_VERITY(inode))
+               fsflags |= FS_VERITY_FL;
        if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode))
                fsflags |= FS_INLINE_DATA_FL;
        if (is_inode_flag_set(inode, FI_PIN_FILE))
@@ -2210,6 +2224,49 @@ out_err:
        return err;
 }
 
+static int f2fs_ioc_get_encryption_policy_ex(struct file *filp,
+                                            unsigned long arg)
+{
+       if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp))))
+               return -EOPNOTSUPP;
+
+       return fscrypt_ioctl_get_policy_ex(filp, (void __user *)arg);
+}
+
+static int f2fs_ioc_add_encryption_key(struct file *filp, unsigned long arg)
+{
+       if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp))))
+               return -EOPNOTSUPP;
+
+       return fscrypt_ioctl_add_key(filp, (void __user *)arg);
+}
+
+static int f2fs_ioc_remove_encryption_key(struct file *filp, unsigned long arg)
+{
+       if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp))))
+               return -EOPNOTSUPP;
+
+       return fscrypt_ioctl_remove_key(filp, (void __user *)arg);
+}
+
+static int f2fs_ioc_remove_encryption_key_all_users(struct file *filp,
+                                                   unsigned long arg)
+{
+       if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp))))
+               return -EOPNOTSUPP;
+
+       return fscrypt_ioctl_remove_key_all_users(filp, (void __user *)arg);
+}
+
+static int f2fs_ioc_get_encryption_key_status(struct file *filp,
+                                             unsigned long arg)
+{
+       if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp))))
+               return -EOPNOTSUPP;
+
+       return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
+}
+
 static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
@@ -3088,6 +3145,30 @@ static int f2fs_ioc_resize_fs(struct file *filp, unsigned long arg)
        return ret;
 }
 
+static int f2fs_ioc_enable_verity(struct file *filp, unsigned long arg)
+{
+       struct inode *inode = file_inode(filp);
+
+       f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
+
+       if (!f2fs_sb_has_verity(F2FS_I_SB(inode))) {
+               f2fs_warn(F2FS_I_SB(inode),
+                         "Can't enable fs-verity on inode %lu: the verity feature is not enabled on this filesystem.\n",
+                         inode->i_ino);
+               return -EOPNOTSUPP;
+       }
+
+       return fsverity_ioctl_enable(filp, (const void __user *)arg);
+}
+
+static int f2fs_ioc_measure_verity(struct file *filp, unsigned long arg)
+{
+       if (!f2fs_sb_has_verity(F2FS_I_SB(file_inode(filp))))
+               return -EOPNOTSUPP;
+
+       return fsverity_ioctl_measure(filp, (void __user *)arg);
+}
+
 static int f2fs_get_volume_name(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
@@ -3184,6 +3265,16 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return f2fs_ioc_get_encryption_policy(filp, arg);
        case F2FS_IOC_GET_ENCRYPTION_PWSALT:
                return f2fs_ioc_get_encryption_pwsalt(filp, arg);
+       case FS_IOC_GET_ENCRYPTION_POLICY_EX:
+               return f2fs_ioc_get_encryption_policy_ex(filp, arg);
+       case FS_IOC_ADD_ENCRYPTION_KEY:
+               return f2fs_ioc_add_encryption_key(filp, arg);
+       case FS_IOC_REMOVE_ENCRYPTION_KEY:
+               return f2fs_ioc_remove_encryption_key(filp, arg);
+       case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
+               return f2fs_ioc_remove_encryption_key_all_users(filp, arg);
+       case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
+               return f2fs_ioc_get_encryption_key_status(filp, arg);
        case F2FS_IOC_GARBAGE_COLLECT:
                return f2fs_ioc_gc(filp, arg);
        case F2FS_IOC_GARBAGE_COLLECT_RANGE:
@@ -3210,6 +3301,10 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return f2fs_ioc_precache_extents(filp, arg);
        case F2FS_IOC_RESIZE_FS:
                return f2fs_ioc_resize_fs(filp, arg);
+       case FS_IOC_ENABLE_VERITY:
+               return f2fs_ioc_enable_verity(filp, arg);
+       case FS_IOC_MEASURE_VERITY:
+               return f2fs_ioc_measure_verity(filp, arg);
        case F2FS_IOC_GET_VOLUME_NAME:
                return f2fs_get_volume_name(filp, arg);
        case F2FS_IOC_SET_VOLUME_NAME:
@@ -3311,6 +3406,11 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case F2FS_IOC_SET_ENCRYPTION_POLICY:
        case F2FS_IOC_GET_ENCRYPTION_PWSALT:
        case F2FS_IOC_GET_ENCRYPTION_POLICY:
+       case FS_IOC_GET_ENCRYPTION_POLICY_EX:
+       case FS_IOC_ADD_ENCRYPTION_KEY:
+       case FS_IOC_REMOVE_ENCRYPTION_KEY:
+       case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
+       case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
        case F2FS_IOC_GARBAGE_COLLECT:
        case F2FS_IOC_GARBAGE_COLLECT_RANGE:
        case F2FS_IOC_WRITE_CHECKPOINT:
@@ -3324,6 +3424,8 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case F2FS_IOC_SET_PIN_FILE:
        case F2FS_IOC_PRECACHE_EXTENTS:
        case F2FS_IOC_RESIZE_FS:
+       case FS_IOC_ENABLE_VERITY:
+       case FS_IOC_MEASURE_VERITY:
        case F2FS_IOC_GET_VOLUME_NAME:
        case F2FS_IOC_SET_VOLUME_NAME:
                break;