ntfs3: add legacy ntfs file operations
authorChristian Brauner <brauner@kernel.org>
Tue, 16 Apr 2024 10:20:50 +0000 (12:20 +0200)
committerChristian Brauner <brauner@kernel.org>
Tue, 23 Apr 2024 07:39:07 +0000 (09:39 +0200)
To ensure that ioctl()s can't be used to circumvent write restrictions.

Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/ntfs3/dir.c
fs/ntfs3/file.c
fs/ntfs3/inode.c
fs/ntfs3/ntfs_fs.h

index 5cf3d9decf646b1935517e8b564d807626e60e0f..263635199b60d38a23b98c10f31d2105d832eda4 100644 (file)
@@ -616,4 +616,11 @@ const struct file_operations ntfs_dir_operations = {
        .compat_ioctl   = ntfs_compat_ioctl,
 #endif
 };
+
+const struct file_operations ntfs_legacy_dir_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_read_dir,
+       .iterate_shared = ntfs_readdir,
+       .open           = ntfs_file_open,
+};
 // clang-format on
index 5418662c80d8878afe72a8b8e8ffc43cc834b176..b73969e05052ae8bcd49740057405e3e71c0852a 100644 (file)
@@ -1236,4 +1236,12 @@ const struct file_operations ntfs_file_operations = {
        .fallocate      = ntfs_fallocate,
        .release        = ntfs_file_release,
 };
+
+const struct file_operations ntfs_legacy_file_operations = {
+       .llseek         = generic_file_llseek,
+       .read_iter      = ntfs_file_read_iter,
+       .splice_read    = ntfs_file_splice_read,
+       .open           = ntfs_file_open,
+       .release        = ntfs_file_release,
+};
 // clang-format on
index eb7a8c9fba0183f40096d673473be4dffaa7c4c8..d273eda1cf45d68e90cc56866fe689a629be43b5 100644 (file)
@@ -440,7 +440,10 @@ end_enum:
                 * Usually a hard links to directories are disabled.
                 */
                inode->i_op = &ntfs_dir_inode_operations;
-               inode->i_fop = &ntfs_dir_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_dir_operations;
+               else
+                       inode->i_fop = &ntfs_dir_operations;
                ni->i_valid = 0;
        } else if (S_ISLNK(mode)) {
                ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
@@ -450,7 +453,10 @@ end_enum:
        } else if (S_ISREG(mode)) {
                ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
                inode->i_op = &ntfs_file_inode_operations;
-               inode->i_fop = &ntfs_file_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_file_operations;
+               else
+                       inode->i_fop = &ntfs_file_operations;
                inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
                                                              &ntfs_aops;
                if (ino != MFT_REC_MFT)
@@ -1614,7 +1620,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
 
        if (S_ISDIR(mode)) {
                inode->i_op = &ntfs_dir_inode_operations;
-               inode->i_fop = &ntfs_dir_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_dir_operations;
+               else
+                       inode->i_fop = &ntfs_dir_operations;
        } else if (S_ISLNK(mode)) {
                inode->i_op = &ntfs_link_inode_operations;
                inode->i_fop = NULL;
@@ -1623,7 +1632,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
                inode_nohighmem(inode);
        } else if (S_ISREG(mode)) {
                inode->i_op = &ntfs_file_inode_operations;
-               inode->i_fop = &ntfs_file_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_file_operations;
+               else
+                       inode->i_fop = &ntfs_file_operations;
                inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
                                                              &ntfs_aops;
                init_rwsem(&ni->file.run_lock);
index 184c8bc76b927d0f3376724efbaff79bfb33766b..5f4d288c6adfb955fb21bc513cae69f80cb61b20 100644 (file)
@@ -493,6 +493,7 @@ struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
                           struct ntfs_fnd *fnd);
 bool dir_is_empty(struct inode *dir);
 extern const struct file_operations ntfs_dir_operations;
+extern const struct file_operations ntfs_legacy_dir_operations;
 
 /* Globals from file.c */
 int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
@@ -507,6 +508,7 @@ long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg);
 extern const struct inode_operations ntfs_special_inode_operations;
 extern const struct inode_operations ntfs_file_inode_operations;
 extern const struct file_operations ntfs_file_operations;
+extern const struct file_operations ntfs_legacy_file_operations;
 
 /* Globals from frecord.c */
 void ni_remove_mi(struct ntfs_inode *ni, struct mft_inode *mi);