]> Git Repo - linux.git/commitdiff
Merge tag 'y2038-vfs' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground
authorLinus Torvalds <[email protected]>
Thu, 19 Sep 2019 16:42:37 +0000 (09:42 -0700)
committerLinus Torvalds <[email protected]>
Thu, 19 Sep 2019 16:42:37 +0000 (09:42 -0700)
Pull y2038 vfs updates from Arnd Bergmann:
 "Add inode timestamp clamping.

  This series from Deepa Dinamani adds a per-superblock minimum/maximum
  timestamp limit for a file system, and clamps timestamps as they are
  written, to avoid random behavior from integer overflow as well as
  having different time stamps on disk vs in memory.

  At mount time, a warning is now printed for any file system that can
  represent current timestamps but not future timestamps more than 30
  years into the future, similar to the arbitrary 30 year limit that was
  added to settimeofday().

  This was picked as a compromise to warn users to migrate to other file
  systems (e.g. ext4 instead of ext3) when they need the file system to
  survive beyond 2038 (or similar limits in other file systems), but not
  get in the way of normal usage"

* tag 'y2038-vfs' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground:
  ext4: Reduce ext4 timestamp warnings
  isofs: Initialize filesystem timestamp ranges
  pstore: fs superblock limits
  fs: omfs: Initialize filesystem timestamp ranges
  fs: hpfs: Initialize filesystem timestamp ranges
  fs: ceph: Initialize filesystem timestamp ranges
  fs: sysv: Initialize filesystem timestamp ranges
  fs: affs: Initialize filesystem timestamp ranges
  fs: fat: Initialize filesystem timestamp ranges
  fs: cifs: Initialize filesystem timestamp ranges
  fs: nfs: Initialize filesystem timestamp ranges
  ext4: Initialize timestamps limits
  9p: Fill min and max timestamps in sb
  fs: Fill in max and min timestamps in superblock
  utimes: Clamp the timestamps before update
  mount: Add mount warning for impending timestamp expiry
  timestamp_truncate: Replace users of timespec64_trunc
  vfs: Add timestamp_truncate() api
  vfs: Add file timestamp range support

1  2 
fs/cifs/cifsfs.c
fs/ext4/ext4.h
fs/ext4/super.c
fs/f2fs/file.c
fs/namespace.c
fs/super.c
fs/xfs/xfs_super.c
include/linux/fs.h

diff --combined fs/cifs/cifsfs.c
index 4e2f74894e9b3c34eece9d115e6001cb7f96a5e6,7a75726442ad2e0fe7710a234650409db8f99d79..e8afff702bb8e60bba9c43fbc593fd6f9e0a1b74
  #include "dfs_cache.h"
  #endif
  
+ /*
+  * DOS dates from 1980/1/1 through 2107/12/31
+  * Protocol specifications indicate the range should be to 119, which
+  * limits maximum year to 2099. But this range has not been checked.
+  */
+ #define SMB_DATE_MAX (127<<9 | 12<<5 | 31)
+ #define SMB_DATE_MIN (0<<9 | 1<<5 | 1)
+ #define SMB_TIME_MAX (23<<11 | 59<<5 | 29)
  int cifsFYI = 0;
  bool traceSMB;
  bool enable_oplocks = true;
@@@ -142,6 -151,7 +151,7 @@@ cifs_read_super(struct super_block *sb
        struct inode *inode;
        struct cifs_sb_info *cifs_sb;
        struct cifs_tcon *tcon;
+       struct timespec64 ts;
        int rc = 0;
  
        cifs_sb = CIFS_SB(sb);
        /* BB FIXME fix time_gran to be larger for LANMAN sessions */
        sb->s_time_gran = 100;
  
+       if (tcon->unix_ext) {
+               ts = cifs_NTtimeToUnix(0);
+               sb->s_time_min = ts.tv_sec;
+               ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
+               sb->s_time_max = ts.tv_sec;
+       } else {
+               ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
+               sb->s_time_min = ts.tv_sec;
+               ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX), cpu_to_le16(SMB_TIME_MAX), 0);
+               sb->s_time_max = ts.tv_sec;
+       }
        sb->s_magic = CIFS_MAGIC_NUMBER;
        sb->s_op = &cifs_super_ops;
        sb->s_xattr = cifs_xattr_handlers;
@@@ -1601,6 -1623,7 +1623,6 @@@ MODULE_DESCRIPTIO
        ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and "
        "also older servers complying with the SNIA CIFS Specification)");
  MODULE_VERSION(CIFS_VERSION);
 -MODULE_SOFTDEP("pre: des");
  MODULE_SOFTDEP("pre: ecb");
  MODULE_SOFTDEP("pre: hmac");
  MODULE_SOFTDEP("pre: md4");
diff --combined fs/ext4/ext4.h
index 9c7f4036021b436d47be4589ff943b44216f425c,24b14bd3feabc53b1ca4ae5b992acf98b4e4a906..42c6e4a5e673f7c2de8f1d7c182cf3979a78c007
@@@ -41,7 -41,6 +41,7 @@@
  #endif
  
  #include <linux/fscrypt.h>
 +#include <linux/fsverity.h>
  
  #include <linux/compiler.h>
  
@@@ -396,7 -395,6 +396,7 @@@ struct flex_groups 
  #define EXT4_TOPDIR_FL                        0x00020000 /* Top of directory hierarchies*/
  #define EXT4_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
  #define EXT4_EXTENTS_FL                       0x00080000 /* Inode uses extents */
 +#define EXT4_VERITY_FL                        0x00100000 /* Verity protected inode */
  #define EXT4_EA_INODE_FL              0x00200000 /* Inode used for large EA */
  #define EXT4_EOFBLOCKS_FL             0x00400000 /* Blocks allocated beyond EOF */
  #define EXT4_INLINE_DATA_FL           0x10000000 /* Inode has inline data. */
  #define EXT4_CASEFOLD_FL              0x40000000 /* Casefolded file */
  #define EXT4_RESERVED_FL              0x80000000 /* reserved for ext4 lib */
  
 -#define EXT4_FL_USER_VISIBLE          0x704BDFFF /* User visible flags */
 +#define EXT4_FL_USER_VISIBLE          0x705BDFFF /* User visible flags */
  #define EXT4_FL_USER_MODIFIABLE               0x604BC0FF /* User modifiable flags */
  
  /* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */
@@@ -469,7 -467,6 +469,7 @@@ enum 
        EXT4_INODE_TOPDIR       = 17,   /* Top of directory hierarchies*/
        EXT4_INODE_HUGE_FILE    = 18,   /* Set to each huge file */
        EXT4_INODE_EXTENTS      = 19,   /* Inode uses extents */
 +      EXT4_INODE_VERITY       = 20,   /* Verity protected inode */
        EXT4_INODE_EA_INODE     = 21,   /* Inode used for large EA */
        EXT4_INODE_EOFBLOCKS    = 22,   /* Blocks allocated beyond EOF */
        EXT4_INODE_INLINE_DATA  = 28,   /* Data in inode. */
@@@ -515,7 -512,6 +515,7 @@@ static inline void ext4_check_flag_valu
        CHECK_FLAG_VALUE(TOPDIR);
        CHECK_FLAG_VALUE(HUGE_FILE);
        CHECK_FLAG_VALUE(EXTENTS);
 +      CHECK_FLAG_VALUE(VERITY);
        CHECK_FLAG_VALUE(EA_INODE);
        CHECK_FLAG_VALUE(EOFBLOCKS);
        CHECK_FLAG_VALUE(INLINE_DATA);
@@@ -832,11 -828,13 +832,13 @@@ static inline void ext4_decode_extra_ti
  
  #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)                         \
  do {                                                                          \
-       (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec);                \
        if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra))     {\
+               (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec);        \
                (raw_inode)->xtime ## _extra =                                  \
                                ext4_encode_extra_time(&(inode)->xtime);        \
                }                                                               \
+       else    \
+               (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (inode)->xtime.tv_sec, S32_MIN, S32_MAX));    \
  } while (0)
  
  #define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode)                              \
@@@ -1564,7 -1562,6 +1566,7 @@@ enum 
        EXT4_STATE_MAY_INLINE_DATA,     /* may have in-inode data */
        EXT4_STATE_EXT_PRECACHED,       /* extents have been precached */
        EXT4_STATE_LUSTRE_EA_INODE,     /* Lustre-style ea_inode */
 +      EXT4_STATE_VERITY_IN_PROGRESS,  /* building fs-verity Merkle tree */
  };
  
  #define EXT4_INODE_BIT_FNS(name, field, offset)                               \
@@@ -1615,12 -1612,6 +1617,12 @@@ static inline void ext4_clear_state_fla
  #define EXT4_SB(sb)   (sb)
  #endif
  
 +static inline bool ext4_verity_in_progress(struct inode *inode)
 +{
 +      return IS_ENABLED(CONFIG_FS_VERITY) &&
 +             ext4_test_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
 +}
 +
  #define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
  
  /*
  
  #define EXT4_GOOD_OLD_INODE_SIZE 128
  
+ #define EXT4_EXTRA_TIMESTAMP_MAX      (((s64)1 << 34) - 1  + S32_MIN)
+ #define EXT4_NON_EXTRA_TIMESTAMP_MAX  S32_MAX
+ #define EXT4_TIMESTAMP_MIN            S32_MIN
  /*
   * Feature set definitions
   */
  #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM  0x0400
  #define EXT4_FEATURE_RO_COMPAT_READONLY               0x1000
  #define EXT4_FEATURE_RO_COMPAT_PROJECT                0x2000
 +#define EXT4_FEATURE_RO_COMPAT_VERITY         0x8000
  
  #define EXT4_FEATURE_INCOMPAT_COMPRESSION     0x0001
  #define EXT4_FEATURE_INCOMPAT_FILETYPE                0x0002
@@@ -1768,7 -1762,6 +1774,7 @@@ EXT4_FEATURE_RO_COMPAT_FUNCS(bigalloc
  EXT4_FEATURE_RO_COMPAT_FUNCS(metadata_csum,   METADATA_CSUM)
  EXT4_FEATURE_RO_COMPAT_FUNCS(readonly,                READONLY)
  EXT4_FEATURE_RO_COMPAT_FUNCS(project,         PROJECT)
 +EXT4_FEATURE_RO_COMPAT_FUNCS(verity,          VERITY)
  
  EXT4_FEATURE_INCOMPAT_FUNCS(compression,      COMPRESSION)
  EXT4_FEATURE_INCOMPAT_FUNCS(filetype,         FILETYPE)
@@@ -1826,8 -1819,7 +1832,8 @@@ EXT4_FEATURE_INCOMPAT_FUNCS(casefold,           
                                         EXT4_FEATURE_RO_COMPAT_BIGALLOC |\
                                         EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
                                         EXT4_FEATURE_RO_COMPAT_QUOTA |\
 -                                       EXT4_FEATURE_RO_COMPAT_PROJECT)
 +                                       EXT4_FEATURE_RO_COMPAT_PROJECT |\
 +                                       EXT4_FEATURE_RO_COMPAT_VERITY)
  
  #define EXTN_FEATURE_FUNCS(ver) \
  static inline bool ext4_has_unknown_ext##ver##_compat_features(struct super_block *sb) \
@@@ -3191,8 -3183,6 +3197,8 @@@ static inline void ext4_set_de_type(str
  extern int ext4_mpage_readpages(struct address_space *mapping,
                                struct list_head *pages, struct page *page,
                                unsigned nr_pages, bool is_readahead);
 +extern int __init ext4_init_post_read_processing(void);
 +extern void ext4_exit_post_read_processing(void);
  
  /* symlink.c */
  extern const struct inode_operations ext4_encrypted_symlink_inode_operations;
@@@ -3299,9 -3289,6 +3305,9 @@@ extern int ext4_bio_write_page(struct e
  /* mmp.c */
  extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t);
  
 +/* verity.c */
 +extern const struct fsverity_operations ext4_verityops;
 +
  /*
   * Add new method to test whether block and inode bitmaps are properly
   * initialized. With uninit_bg reading the block from disk is not enough
diff --combined fs/ext4/super.c
index 27cd622676e717c597d0f0d161b7f41d5bb82a51,3ea2d60f33aab7c1801ce9e3a7da8cf496470c65..3db5f17228b7691f9208252e937c16349d486e12
@@@ -1107,9 -1107,6 +1107,9 @@@ static int ext4_drop_inode(struct inod
  {
        int drop = generic_drop_inode(inode);
  
 +      if (!drop)
 +              drop = fscrypt_drop_inode(inode);
 +
        trace_ext4_drop_inode(inode, drop);
        return drop;
  }
@@@ -1182,7 -1179,6 +1182,7 @@@ void ext4_clear_inode(struct inode *ino
                EXT4_I(inode)->jinode = NULL;
        }
        fscrypt_put_encryption_info(inode);
 +      fsverity_cleanup_inode(inode);
  }
  
  static struct inode *ext4_nfs_get_inode(struct super_block *sb,
@@@ -4039,8 -4035,21 +4039,21 @@@ static int ext4_fill_super(struct super
                               sbi->s_inode_size);
                        goto failed_mount;
                }
-               if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)
-                       sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2);
+               /*
+                * i_atime_extra is the last extra field available for [acm]times in
+                * struct ext4_inode. Checking for that field should suffice to ensure
+                * we have extra space for all three.
+                */
+               if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
+                       sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
+                       sb->s_time_gran = 1;
+                       sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
+               } else {
+                       sb->s_time_gran = NSEC_PER_SEC;
+                       sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
+               }
+               sb->s_time_min = EXT4_TIMESTAMP_MIN;
        }
  
        sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
  #ifdef CONFIG_FS_ENCRYPTION
        sb->s_cop = &ext4_cryptops;
  #endif
 +#ifdef CONFIG_FS_VERITY
 +      sb->s_vop = &ext4_verityops;
 +#endif
  #ifdef CONFIG_QUOTA
        sb->dq_op = &ext4_quota_operations;
        if (ext4_has_feature_quota(sb))
@@@ -4426,11 -4432,6 +4439,11 @@@ no_journal
                goto failed_mount_wq;
        }
  
 +      if (ext4_has_feature_verity(sb) && blocksize != PAGE_SIZE) {
 +              ext4_msg(sb, KERN_ERR, "Unsupported blocksize for fs-verity");
 +              goto failed_mount_wq;
 +      }
 +
        if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) &&
            !ext4_has_feature_encrypt(sb)) {
                ext4_set_feature_encrypt(sb);
@@@ -6106,10 -6107,6 +6119,10 @@@ static int __init ext4_init_fs(void
                return err;
  
        err = ext4_init_pending();
 +      if (err)
 +              goto out7;
 +
 +      err = ext4_init_post_read_processing();
        if (err)
                goto out6;
  
@@@ -6151,10 -6148,8 +6164,10 @@@ out3
  out4:
        ext4_exit_pageio();
  out5:
 -      ext4_exit_pending();
 +      ext4_exit_post_read_processing();
  out6:
 +      ext4_exit_pending();
 +out7:
        ext4_exit_es();
  
        return err;
@@@ -6171,7 -6166,6 +6184,7 @@@ static void __exit ext4_exit_fs(void
        ext4_exit_sysfs();
        ext4_exit_system_zone();
        ext4_exit_pageio();
 +      ext4_exit_post_read_processing();
        ext4_exit_es();
        ext4_exit_pending();
  }
diff --combined fs/f2fs/file.c
index 39fffc19e00c910a2b6218d14fd213aa75c0db47,95f48f6b1180e35e91e57a2a82b8975372608dbe..56efde9d36596bd3c9e5bdb328abe6a47df61180
@@@ -493,10 -493,6 +493,10 @@@ static int f2fs_file_open(struct inode 
  {
        int err = fscrypt_file_open(inode, filp);
  
 +      if (err)
 +              return err;
 +
 +      err = fsverity_file_open(inode, filp);
        if (err)
                return err;
  
@@@ -745,15 -741,18 +745,18 @@@ static void __setattr_copy(struct inod
                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;
  
@@@ -782,10 -781,6 +785,10 @@@ int f2fs_setattr(struct dentry *dentry
        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)
@@@ -1713,8 -1708,7 +1716,8 @@@ static const struct 
                FS_PROJINHERIT_FL |     \
                FS_ENCRYPT_FL |         \
                FS_INLINE_DATA_FL |     \
 -              FS_NOCOW_FL)
 +              FS_NOCOW_FL |           \
 +              FS_VERITY_FL)
  
  #define F2FS_SETTABLE_FS_FL (         \
                FS_SYNC_FL |            \
@@@ -1759,8 -1753,6 +1762,8 @@@ static int f2fs_ioc_getflags(struct fil
  
        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))
@@@ -2195,49 -2187,6 +2198,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);
@@@ -3114,30 -3063,6 +3117,30 @@@ static int f2fs_ioc_resize_fs(struct fi
        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);
 +}
 +
  long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  {
        if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp)))))
                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:
                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);
        default:
                return -ENOTTY;
        }
@@@ -3311,11 -3222,6 +3314,11 @@@ long f2fs_compat_ioctl(struct file *fil
        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:
        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:
                break;
        default:
                return -ENOIOCTLCMD;
diff --combined fs/namespace.c
index 227f7b34303465a2621497524dece91038267b23,eae46531405f0dfd79590f60a2dd21cab5612a47..93c043245c463eb77c4c48316e8ba8ae80f47830
@@@ -1643,18 -1643,13 +1643,18 @@@ static inline bool may_mount(void
        return ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN);
  }
  
 +#ifdef        CONFIG_MANDATORY_FILE_LOCKING
  static inline bool may_mandlock(void)
  {
 -#ifndef       CONFIG_MANDATORY_FILE_LOCKING
 -      return false;
 -#endif
        return capable(CAP_SYS_ADMIN);
  }
 +#else
 +static inline bool may_mandlock(void)
 +{
 +      pr_warn("VFS: \"mand\" mount option not supported");
 +      return false;
 +}
 +#endif
  
  /*
   * Now umount can handle mount points as well as block devices.
@@@ -1680,6 -1675,8 +1680,6 @@@ int ksys_umount(char __user *name, int 
        if (!(flags & UMOUNT_NOFOLLOW))
                lookup_flags |= LOOKUP_FOLLOW;
  
 -      lookup_flags |= LOOKUP_NO_EVAL;
 -
        retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
        if (retval)
                goto out;
@@@ -2466,6 -2463,26 +2466,26 @@@ static void set_mount_attributes(struc
        unlock_mount_hash();
  }
  
+ static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount *mnt)
+ {
+       struct super_block *sb = mnt->mnt_sb;
+       if (!__mnt_is_readonly(mnt) &&
+          (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) {
+               char *buf = (char *)__get_free_page(GFP_KERNEL);
+               char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM);
+               struct tm tm;
+               time64_to_tm(sb->s_time_max, 0, &tm);
+               pr_warn("Mounted %s file system at %s supports timestamps until %04ld (0x%llx)\n",
+                       sb->s_type->name, mntpath,
+                       tm.tm_year+1900, (unsigned long long)sb->s_time_max);
+               free_page((unsigned long)buf);
+       }
+ }
  /*
   * Handle reconfiguration of the mountpoint only without alteration of the
   * superblock it refers to.  This is triggered by specifying MS_REMOUNT|MS_BIND
@@@ -2491,6 -2508,9 +2511,9 @@@ static int do_reconfigure_mnt(struct pa
        if (ret == 0)
                set_mount_attributes(mnt, mnt_flags);
        up_write(&sb->s_umount);
+       mnt_warn_timestamp_expiry(path, &mnt->mnt);
        return ret;
  }
  
@@@ -2531,6 -2551,9 +2554,9 @@@ static int do_remount(struct path *path
                }
                up_write(&sb->s_umount);
        }
+       mnt_warn_timestamp_expiry(path, &mnt->mnt);
        put_fs_context(fc);
        return err;
  }
@@@ -2739,8 -2762,13 +2765,13 @@@ static int do_new_mount_fc(struct fs_co
                return PTR_ERR(mnt);
  
        error = do_add_mount(real_mount(mnt), mountpoint, mnt_flags);
-       if (error < 0)
+       if (error < 0) {
                mntput(mnt);
+               return error;
+       }
+       mnt_warn_timestamp_expiry(mountpoint, mnt);
        return error;
  }
  
@@@ -3049,7 -3077,7 +3080,7 @@@ long do_mount(const char *dev_name, con
                return -EINVAL;
  
        /* ... and get the mountpoint */
 -      retval = user_path(dir_name, &path);
 +      retval = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
        if (retval)
                return retval;
  
@@@ -3596,13 -3624,11 +3627,13 @@@ SYSCALL_DEFINE2(pivot_root, const char 
        if (!may_mount())
                return -EPERM;
  
 -      error = user_path_dir(new_root, &new);
 +      error = user_path_at(AT_FDCWD, new_root,
 +                           LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &new);
        if (error)
                goto out0;
  
 -      error = user_path_dir(put_old, &old);
 +      error = user_path_at(AT_FDCWD, put_old,
 +                           LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old);
        if (error)
                goto out1;
  
diff --combined fs/super.c
index 9459ba75a32e3687902384896f506eee2d5ac8b5,3e232e8c51b926e90d1a764f093f5e0ac0da3c82..2d679db9e8c7b64783f34e32e299b8e2d74ed2af
@@@ -32,7 -32,6 +32,7 @@@
  #include <linux/backing-dev.h>
  #include <linux/rculist_bl.h>
  #include <linux/cleancache.h>
 +#include <linux/fscrypt.h>
  #include <linux/fsnotify.h>
  #include <linux/lockdep.h>
  #include <linux/user_namespace.h>
@@@ -258,6 -257,8 +258,8 @@@ static struct super_block *alloc_super(
        s->s_maxbytes = MAX_NON_LFS;
        s->s_op = &default_op;
        s->s_time_gran = 1000000000;
+       s->s_time_min = TIME64_MIN;
+       s->s_time_max = TIME64_MAX;
        s->cleancache_poolid = CLEANCACHE_NO_POOL;
  
        s->s_shrink.seeks = DEFAULT_SEEKS;
@@@ -291,7 -292,6 +293,7 @@@ static void __put_super(struct super_bl
                WARN_ON(s->s_inode_lru.node);
                WARN_ON(!list_empty(&s->s_mounts));
                security_sb_free(s);
 +              fscrypt_sb_free(s);
                put_user_ns(s->s_user_ns);
                kfree(s->s_subtype);
                call_rcu(&s->rcu, destroy_super_rcu);
@@@ -1213,18 -1213,7 +1215,18 @@@ int get_tree_single(struct fs_context *
  }
  EXPORT_SYMBOL(get_tree_single);
  
 +int get_tree_keyed(struct fs_context *fc,
 +                int (*fill_super)(struct super_block *sb,
 +                                  struct fs_context *fc),
 +              void *key)
 +{
 +      fc->s_fs_info = key;
 +      return vfs_get_super(fc, vfs_get_keyed_super, fill_super);
 +}
 +EXPORT_SYMBOL(get_tree_keyed);
 +
  #ifdef CONFIG_BLOCK
 +
  static int set_bdev_super(struct super_block *s, void *data)
  {
        s->s_bdev = data;
        return 0;
  }
  
 +static int set_bdev_super_fc(struct super_block *s, struct fs_context *fc)
 +{
 +      return set_bdev_super(s, fc->sget_key);
 +}
 +
 +static int test_bdev_super_fc(struct super_block *s, struct fs_context *fc)
 +{
 +      return s->s_bdev == fc->sget_key;
 +}
 +
 +/**
 + * get_tree_bdev - Get a superblock based on a single block device
 + * @fc: The filesystem context holding the parameters
 + * @fill_super: Helper to initialise a new superblock
 + */
 +int get_tree_bdev(struct fs_context *fc,
 +              int (*fill_super)(struct super_block *,
 +                                struct fs_context *))
 +{
 +      struct block_device *bdev;
 +      struct super_block *s;
 +      fmode_t mode = FMODE_READ | FMODE_EXCL;
 +      int error = 0;
 +
 +      if (!(fc->sb_flags & SB_RDONLY))
 +              mode |= FMODE_WRITE;
 +
 +      if (!fc->source)
 +              return invalf(fc, "No source specified");
 +
 +      bdev = blkdev_get_by_path(fc->source, mode, fc->fs_type);
 +      if (IS_ERR(bdev)) {
 +              errorf(fc, "%s: Can't open blockdev", fc->source);
 +              return PTR_ERR(bdev);
 +      }
 +
 +      /* Once the superblock is inserted into the list by sget_fc(), s_umount
 +       * will protect the lockfs code from trying to start a snapshot while
 +       * we are mounting
 +       */
 +      mutex_lock(&bdev->bd_fsfreeze_mutex);
 +      if (bdev->bd_fsfreeze_count > 0) {
 +              mutex_unlock(&bdev->bd_fsfreeze_mutex);
 +              warnf(fc, "%pg: Can't mount, blockdev is frozen", bdev);
 +              return -EBUSY;
 +      }
 +
 +      fc->sb_flags |= SB_NOSEC;
 +      fc->sget_key = bdev;
 +      s = sget_fc(fc, test_bdev_super_fc, set_bdev_super_fc);
 +      mutex_unlock(&bdev->bd_fsfreeze_mutex);
 +      if (IS_ERR(s))
 +              return PTR_ERR(s);
 +
 +      if (s->s_root) {
 +              /* Don't summarily change the RO/RW state. */
 +              if ((fc->sb_flags ^ s->s_flags) & SB_RDONLY) {
 +                      warnf(fc, "%pg: Can't mount, would change RO state", bdev);
 +                      deactivate_locked_super(s);
 +                      blkdev_put(bdev, mode);
 +                      return -EBUSY;
 +              }
 +
 +              /*
 +               * s_umount nests inside bd_mutex during
 +               * __invalidate_device().  blkdev_put() acquires
 +               * bd_mutex and can't be called under s_umount.  Drop
 +               * s_umount temporarily.  This is safe as we're
 +               * holding an active reference.
 +               */
 +              up_write(&s->s_umount);
 +              blkdev_put(bdev, mode);
 +              down_write(&s->s_umount);
 +      } else {
 +              s->s_mode = mode;
 +              snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
 +              sb_set_blocksize(s, block_size(bdev));
 +              error = fill_super(s, fc);
 +              if (error) {
 +                      deactivate_locked_super(s);
 +                      return error;
 +              }
 +
 +              s->s_flags |= SB_ACTIVE;
 +              bdev->bd_super = s;
 +      }
 +
 +      BUG_ON(fc->root);
 +      fc->root = dget(s->s_root);
 +      return 0;
 +}
 +EXPORT_SYMBOL(get_tree_bdev);
 +
  static int test_bdev_super(struct super_block *s, void *data)
  {
        return (void *)s->s_bdev == data;
diff --combined fs/xfs/xfs_super.c
index 391b4748cae3462bab567f55ff0ab69ec6257f4e,d3b10900fc247d5eaa27d250b2cfc171851155d6..8d1df9f8be071db3be45ac169e9382f740ffed7e
@@@ -818,8 -818,7 +818,8 @@@ xfs_init_mount_workqueues
                goto out_destroy_buf;
  
        mp->m_cil_workqueue = alloc_workqueue("xfs-cil/%s",
 -                      WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname);
 +                      WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND,
 +                      0, mp->m_fsname);
        if (!mp->m_cil_workqueue)
                goto out_destroy_unwritten;
  
@@@ -1664,6 -1663,8 +1664,8 @@@ xfs_fs_fill_super
        sb->s_maxbytes = xfs_max_file_offset(sb->s_blocksize_bits);
        sb->s_max_links = XFS_MAXLINK;
        sb->s_time_gran = 1;
+       sb->s_time_min = S32_MIN;
+       sb->s_time_max = S32_MAX;
        sb->s_iflags |= SB_I_CGROUPWB;
  
        set_posix_acl_flag(sb);
diff --combined include/linux/fs.h
index ffe35d97afcb4971e7efa86fdac6e1675d100631,7e6be3bf0ce057e50c049a92b81c348e7ad2fd6d..866268c2c6e3a0e127cf87b1276a4ebadf52c37f
@@@ -64,8 -64,6 +64,8 @@@ struct workqueue_struct
  struct iov_iter;
  struct fscrypt_info;
  struct fscrypt_operations;
 +struct fsverity_info;
 +struct fsverity_operations;
  struct fs_context;
  struct fs_parameter_description;
  
@@@ -725,13 -723,11 +725,15 @@@ struct inode 
        struct fscrypt_info     *i_crypt_info;
  #endif
  
 +#ifdef CONFIG_FS_VERITY
 +      struct fsverity_info    *i_verity_info;
 +#endif
 +
        void                    *i_private; /* fs or device private pointer */
  } __randomize_layout;
  
+ struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode);
  static inline unsigned int i_blocksize(const struct inode *node)
  {
        return (1 << node->i_blkbits);
@@@ -1433,10 -1429,6 +1435,10 @@@ struct super_block 
        const struct xattr_handler **s_xattr;
  #ifdef CONFIG_FS_ENCRYPTION
        const struct fscrypt_operations *s_cop;
 +      struct key              *s_master_keys; /* master crypto keys in use */
 +#endif
 +#ifdef CONFIG_FS_VERITY
 +      const struct fsverity_operations *s_vop;
  #endif
        struct hlist_bl_head    s_roots;        /* alternate root dentries for NFS */
        struct list_head        s_mounts;       /* list of mounts; _not_ for fs use */
  
        /* Granularity of c/m/atime in ns (cannot be worse than a second) */
        u32                     s_time_gran;
+       /* Time limits for c/m/atime in seconds */
+       time64_t                   s_time_min;
+       time64_t                   s_time_max;
  #ifdef CONFIG_FSNOTIFY
        __u32                   s_fsnotify_mask;
        struct fsnotify_mark_connector __rcu    *s_fsnotify_marks;
@@@ -1975,7 -1970,6 +1980,7 @@@ struct super_operations 
  #endif
  #define S_ENCRYPTED   16384   /* Encrypted file (using fs/crypto/) */
  #define S_CASEFOLD    32768   /* Casefolded file */
 +#define S_VERITY      65536   /* Verity file (using fs/verity/) */
  
  /*
   * Note that nosuid etc flags are inode-specific: setting some file-system
@@@ -2017,7 -2011,6 +2022,7 @@@ static inline bool sb_rdonly(const stru
  #define IS_DAX(inode)         ((inode)->i_flags & S_DAX)
  #define IS_ENCRYPTED(inode)   ((inode)->i_flags & S_ENCRYPTED)
  #define IS_CASEFOLDED(inode)  ((inode)->i_flags & S_CASEFOLD)
 +#define IS_VERITY(inode)      ((inode)->i_flags & S_VERITY)
  
  #define IS_WHITEOUT(inode)    (S_ISCHR(inode->i_mode) && \
                                 (inode)->i_rdev == WHITEOUT_DEV)
@@@ -3543,8 -3536,6 +3548,8 @@@ extern void inode_nohighmem(struct inod
  /* mm/fadvise.c */
  extern int vfs_fadvise(struct file *file, loff_t offset, loff_t len,
                       int advice);
 +extern int generic_fadvise(struct file *file, loff_t offset, loff_t len,
 +                         int advice);
  
  #if defined(CONFIG_IO_URING)
  extern struct sock *io_uring_get_socket(struct file *file);
@@@ -3567,15 -3558,4 +3572,15 @@@ static inline void simple_fill_fsxattr(
        fa->fsx_xflags = xflags;
  }
  
 +/*
 + * Flush file data before changing attributes.  Caller must hold any locks
 + * required to prevent further writes to this file until we're done setting
 + * flags.
 + */
 +static inline int inode_drain_writes(struct inode *inode)
 +{
 +      inode_dio_wait(inode);
 +      return filemap_write_and_wait(inode->i_mapping);
 +}
 +
  #endif /* _LINUX_FS_H */
This page took 0.126868 seconds and 4 git commands to generate.