Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ntfs3_for_6.12' of https://github.com/Paragon-Software-Group/linux-ntfs3

Pull ntfs3 updates from Konstantin Komarov:
"New:
- implement fallocate for compressed files
- add support for the compression attribute
- optimize large writes to sparse files

Fixes:
- fix several potential deadlock scenarios
- fix various internal bugs detected by syzbot
- add checks before accessing NTFS structures during parsing
- correct the format of output messages

Refactoring:
- replace fsparam_flag_no with fsparam_flag in options parser
- remove unused functions and macros"

* tag 'ntfs3_for_6.12' of https://github.com/Paragon-Software-Group/linux-ntfs3: (25 commits)
fs/ntfs3: Format output messages like others fs in kernel
fs/ntfs3: Additional check in ntfs_file_release
fs/ntfs3: Fix general protection fault in run_is_mapped_full
fs/ntfs3: Sequential field availability check in mi_enum_attr()
fs/ntfs3: Additional check in ni_clear()
fs/ntfs3: Fix possible deadlock in mi_read
ntfs3: Change to non-blocking allocation in ntfs_d_hash
fs/ntfs3: Remove unused al_delete_le
fs/ntfs3: Rename ntfs3_setattr into ntfs_setattr
fs/ntfs3: Replace fsparam_flag_no -> fsparam_flag
fs/ntfs3: Add support for the compression attribute
fs/ntfs3: Implement fallocate for compressed files
fs/ntfs3: Make checks in run_unpack more clear
fs/ntfs3: Add rough attr alloc_size check
fs/ntfs3: Stale inode instead of bad
fs/ntfs3: Refactor enum_rstbl to suppress static checker
fs/ntfs3: Fix sparse warning in ni_fiemap
fs/ntfs3: Fix warning possible deadlock in ntfs_set_state
fs/ntfs3: Fix sparse warning for bigendian
fs/ntfs3: Separete common code for file_read/write iter/splice
...

+420 -207
+86 -10
fs/ntfs3/attrib.c
··· 976 976 goto out; 977 977 978 978 /* Check for compressed frame. */ 979 - err = attr_is_frame_compressed(ni, attr, vcn >> NTFS_LZNT_CUNIT, &hint); 979 + err = attr_is_frame_compressed(ni, attr_b, vcn >> NTFS_LZNT_CUNIT, 980 + &hint); 980 981 if (err) 981 982 goto out; 982 983 983 984 if (hint) { 984 985 /* if frame is compressed - don't touch it. */ 985 986 *lcn = COMPRESSED_LCN; 986 - *len = hint; 987 - err = -EOPNOTSUPP; 987 + /* length to the end of frame. */ 988 + *len = NTFS_LZNT_CLUSTERS - (vcn & (NTFS_LZNT_CLUSTERS - 1)); 989 + err = 0; 988 990 goto out; 989 991 } 990 992 ··· 1029 1027 1030 1028 /* Check if 'vcn' and 'vcn0' in different attribute segments. */ 1031 1029 if (vcn < svcn || evcn1 <= vcn) { 1032 - /* Load attribute for truncated vcn. */ 1033 - attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, 1034 - &vcn, &mi); 1035 - if (!attr) { 1030 + struct ATTRIB *attr2; 1031 + /* Load runs for truncated vcn. */ 1032 + attr2 = ni_find_attr(ni, attr_b, &le_b, ATTR_DATA, NULL, 1033 + 0, &vcn, &mi); 1034 + if (!attr2) { 1036 1035 err = -EINVAL; 1037 1036 goto out; 1038 1037 } 1039 - svcn = le64_to_cpu(attr->nres.svcn); 1040 - evcn1 = le64_to_cpu(attr->nres.evcn) + 1; 1041 - err = attr_load_runs(attr, ni, run, NULL); 1038 + evcn1 = le64_to_cpu(attr2->nres.evcn) + 1; 1039 + err = attr_load_runs(attr2, ni, run, NULL); 1042 1040 if (err) 1043 1041 goto out; 1044 1042 } ··· 1519 1517 1520 1518 /* 1521 1519 * attr_is_frame_compressed - Used to detect compressed frame. 1520 + * 1521 + * attr - base (primary) attribute segment. 1522 + * Only base segments contains valid 'attr->nres.c_unit' 1522 1523 */ 1523 1524 int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr, 1524 1525 CLST frame, CLST *clst_data) ··· 2604 2599 up_write(&ni->file.run_lock); 2605 2600 2606 2601 return err; 2602 + } 2603 + 2604 + /* 2605 + * Change the compression of data attribute 2606 + */ 2607 + int attr_set_compress(struct ntfs_inode *ni, bool compr) 2608 + { 2609 + struct ATTRIB *attr; 2610 + struct mft_inode *mi; 2611 + 2612 + attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, &mi); 2613 + if (!attr) 2614 + return -ENOENT; 2615 + 2616 + if (is_attr_compressed(attr) == !!compr) { 2617 + /* Already required compressed state. */ 2618 + return 0; 2619 + } 2620 + 2621 + if (attr->non_res) { 2622 + u16 run_off; 2623 + u32 run_size; 2624 + char *run; 2625 + 2626 + if (attr->nres.data_size) { 2627 + /* 2628 + * There are rare cases when it possible to change 2629 + * compress state without big changes. 2630 + * TODO: Process these cases. 2631 + */ 2632 + return -EOPNOTSUPP; 2633 + } 2634 + 2635 + run_off = le16_to_cpu(attr->nres.run_off); 2636 + run_size = le32_to_cpu(attr->size) - run_off; 2637 + run = Add2Ptr(attr, run_off); 2638 + 2639 + if (!compr) { 2640 + /* remove field 'attr->nres.total_size'. */ 2641 + memmove(run - 8, run, run_size); 2642 + run_off -= 8; 2643 + } 2644 + 2645 + if (!mi_resize_attr(mi, attr, compr ? +8 : -8)) { 2646 + /* 2647 + * Ignore rare case when there are no 8 bytes in record with attr. 2648 + * TODO: split attribute. 2649 + */ 2650 + return -EOPNOTSUPP; 2651 + } 2652 + 2653 + if (compr) { 2654 + /* Make a gap for 'attr->nres.total_size'. */ 2655 + memmove(run + 8, run, run_size); 2656 + run_off += 8; 2657 + attr->nres.total_size = attr->nres.alloc_size; 2658 + } 2659 + attr->nres.run_off = cpu_to_le16(run_off); 2660 + } 2661 + 2662 + /* Update data attribute flags. */ 2663 + if (compr) { 2664 + attr->flags |= ATTR_FLAG_COMPRESSED; 2665 + attr->nres.c_unit = NTFS_LZNT_CUNIT; 2666 + } else { 2667 + attr->flags &= ~ATTR_FLAG_COMPRESSED; 2668 + attr->nres.c_unit = 0; 2669 + } 2670 + mi->dirty = true; 2671 + 2672 + return 0; 2607 2673 }
-53
fs/ntfs3/attrlist.c
··· 382 382 return true; 383 383 } 384 384 385 - /* 386 - * al_delete_le - Delete first le from the list which matches its parameters. 387 - */ 388 - bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn, 389 - const __le16 *name, u8 name_len, const struct MFT_REF *ref) 390 - { 391 - u16 size; 392 - struct ATTR_LIST_ENTRY *le; 393 - size_t off; 394 - typeof(ni->attr_list) *al = &ni->attr_list; 395 - 396 - /* Scan forward to the first le that matches the input. */ 397 - le = al_find_ex(ni, NULL, type, name, name_len, &vcn); 398 - if (!le) 399 - return false; 400 - 401 - off = PtrOffset(al->le, le); 402 - 403 - next: 404 - if (off >= al->size) 405 - return false; 406 - if (le->type != type) 407 - return false; 408 - if (le->name_len != name_len) 409 - return false; 410 - if (name_len && ntfs_cmp_names(le_name(le), name_len, name, name_len, 411 - ni->mi.sbi->upcase, true)) 412 - return false; 413 - if (le64_to_cpu(le->vcn) != vcn) 414 - return false; 415 - 416 - /* 417 - * The caller specified a segment reference, so we have to 418 - * scan through the matching entries until we find that segment 419 - * reference or we run of matching entries. 420 - */ 421 - if (ref && memcmp(ref, &le->ref, sizeof(*ref))) { 422 - off += le16_to_cpu(le->size); 423 - le = Add2Ptr(al->le, off); 424 - goto next; 425 - } 426 - 427 - /* Save on stack the size of 'le'. */ 428 - size = le16_to_cpu(le->size); 429 - /* Delete the le. */ 430 - memmove(le, Add2Ptr(le, size), al->size - (off + size)); 431 - 432 - al->size -= size; 433 - al->dirty = true; 434 - 435 - return true; 436 - } 437 - 438 385 int al_update(struct ntfs_inode *ni, int sync) 439 386 { 440 387 int err;
+148 -57
fs/ntfs3/file.c
··· 82 82 struct fileattr *fa) 83 83 { 84 84 struct inode *inode = d_inode(dentry); 85 + struct ntfs_inode *ni = ntfs_i(inode); 85 86 u32 flags = fa->flags; 86 87 unsigned int new_fl = 0; 87 88 88 89 if (fileattr_has_fsx(fa)) 89 90 return -EOPNOTSUPP; 90 91 91 - if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL)) 92 + if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_COMPR_FL)) 92 93 return -EOPNOTSUPP; 93 94 94 95 if (flags & FS_IMMUTABLE_FL) ··· 97 96 98 97 if (flags & FS_APPEND_FL) 99 98 new_fl |= S_APPEND; 99 + 100 + /* Allowed to change compression for empty files and for directories only. */ 101 + if (!is_dedup(ni) && !is_encrypted(ni) && 102 + (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { 103 + /* Change compress state. */ 104 + int err = ni_set_compress(inode, flags & FS_COMPR_FL); 105 + if (err) 106 + return err; 107 + } 100 108 101 109 inode_set_flags(inode, new_fl, S_IMMUTABLE | S_APPEND); 102 110 ··· 417 407 err = 0; 418 408 } 419 409 410 + if (file && is_sparsed(ni)) { 411 + /* 412 + * This code optimizes large writes to sparse file. 413 + * TODO: merge this fragment with fallocate fragment. 414 + */ 415 + struct ntfs_sb_info *sbi = ni->mi.sbi; 416 + CLST vcn = pos >> sbi->cluster_bits; 417 + CLST cend = bytes_to_cluster(sbi, end); 418 + CLST cend_v = bytes_to_cluster(sbi, ni->i_valid); 419 + CLST lcn, clen; 420 + bool new; 421 + 422 + if (cend_v > cend) 423 + cend_v = cend; 424 + 425 + /* 426 + * Allocate and zero new clusters. 427 + * Zeroing these clusters may be too long. 428 + */ 429 + for (; vcn < cend_v; vcn += clen) { 430 + err = attr_data_get_block(ni, vcn, cend_v - vcn, &lcn, 431 + &clen, &new, true); 432 + if (err) 433 + goto out; 434 + } 435 + /* 436 + * Allocate but not zero new clusters. 437 + */ 438 + for (; vcn < cend; vcn += clen) { 439 + err = attr_data_get_block(ni, vcn, cend - vcn, &lcn, 440 + &clen, &new, false); 441 + if (err) 442 + goto out; 443 + } 444 + } 445 + 420 446 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); 421 447 mark_inode_dirty(inode); 422 448 ··· 529 483 } 530 484 531 485 /* 532 - * ntfs_fallocate 486 + * ntfs_fallocate - file_operations::ntfs_fallocate 533 487 * 534 488 * Preallocate space for a file. This implements ntfs's fallocate file 535 489 * operation, which gets called from sys_fallocate system call. User ··· 664 618 ni_lock(ni); 665 619 err = attr_collapse_range(ni, vbo, len); 666 620 ni_unlock(ni); 621 + if (err) 622 + goto out; 667 623 } else if (mode & FALLOC_FL_INSERT_RANGE) { 668 624 /* Check new size. */ 669 625 err = inode_newsize_ok(inode, new_size); ··· 788 740 } 789 741 790 742 /* 791 - * ntfs3_setattr - inode_operations::setattr 743 + * ntfs_setattr - inode_operations::setattr 792 744 */ 793 - int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 794 - struct iattr *attr) 745 + int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 746 + struct iattr *attr) 795 747 { 796 748 struct inode *inode = d_inode(dentry); 797 749 struct ntfs_inode *ni = ntfs_i(inode); ··· 851 803 return err; 852 804 } 853 805 854 - static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) 806 + /* 807 + * check_read_restriction: 808 + * common code for ntfs_file_read_iter and ntfs_file_splice_read 809 + */ 810 + static int check_read_restriction(struct inode *inode) 855 811 { 856 - struct file *file = iocb->ki_filp; 857 - struct inode *inode = file_inode(file); 858 812 struct ntfs_inode *ni = ntfs_i(inode); 859 813 860 814 if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ··· 866 816 ntfs_inode_warn(inode, "encrypted i/o not supported"); 867 817 return -EOPNOTSUPP; 868 818 } 819 + 820 + #ifndef CONFIG_NTFS3_LZX_XPRESS 821 + if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) { 822 + ntfs_inode_warn( 823 + inode, 824 + "activate CONFIG_NTFS3_LZX_XPRESS to read external compressed files"); 825 + return -EOPNOTSUPP; 826 + } 827 + #endif 828 + 829 + if (is_dedup(ni)) { 830 + ntfs_inode_warn(inode, "read deduplicated not supported"); 831 + return -EOPNOTSUPP; 832 + } 833 + 834 + return 0; 835 + } 836 + 837 + /* 838 + * ntfs_file_read_iter - file_operations::read_iter 839 + */ 840 + static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) 841 + { 842 + struct file *file = iocb->ki_filp; 843 + struct inode *inode = file_inode(file); 844 + struct ntfs_inode *ni = ntfs_i(inode); 845 + ssize_t err; 846 + 847 + err = check_read_restriction(inode); 848 + if (err) 849 + return err; 869 850 870 851 if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { 871 852 ntfs_inode_warn(inode, "direct i/o + compressed not supported"); 872 853 return -EOPNOTSUPP; 873 854 } 874 855 875 - #ifndef CONFIG_NTFS3_LZX_XPRESS 876 - if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) { 877 - ntfs_inode_warn( 878 - inode, 879 - "activate CONFIG_NTFS3_LZX_XPRESS to read external compressed files"); 880 - return -EOPNOTSUPP; 881 - } 882 - #endif 883 - 884 - if (is_dedup(ni)) { 885 - ntfs_inode_warn(inode, "read deduplicated not supported"); 886 - return -EOPNOTSUPP; 887 - } 888 - 889 856 return generic_file_read_iter(iocb, iter); 890 857 } 891 858 859 + /* 860 + * ntfs_file_splice_read - file_operations::splice_read 861 + */ 892 862 static ssize_t ntfs_file_splice_read(struct file *in, loff_t *ppos, 893 863 struct pipe_inode_info *pipe, size_t len, 894 864 unsigned int flags) 895 865 { 896 866 struct inode *inode = file_inode(in); 897 - struct ntfs_inode *ni = ntfs_i(inode); 867 + ssize_t err; 898 868 899 - if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) 900 - return -EIO; 901 - 902 - if (is_encrypted(ni)) { 903 - ntfs_inode_warn(inode, "encrypted i/o not supported"); 904 - return -EOPNOTSUPP; 905 - } 906 - 907 - #ifndef CONFIG_NTFS3_LZX_XPRESS 908 - if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) { 909 - ntfs_inode_warn( 910 - inode, 911 - "activate CONFIG_NTFS3_LZX_XPRESS to read external compressed files"); 912 - return -EOPNOTSUPP; 913 - } 914 - #endif 915 - 916 - if (is_dedup(ni)) { 917 - ntfs_inode_warn(inode, "read deduplicated not supported"); 918 - return -EOPNOTSUPP; 919 - } 869 + err = check_read_restriction(inode); 870 + if (err) 871 + return err; 920 872 921 873 return filemap_splice_read(in, ppos, pipe, len, flags); 922 874 } ··· 1186 1134 } 1187 1135 1188 1136 /* 1189 - * ntfs_file_write_iter - file_operations::write_iter 1137 + * check_write_restriction: 1138 + * common code for ntfs_file_write_iter and ntfs_file_splice_write 1190 1139 */ 1191 - static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 1140 + static int check_write_restriction(struct inode *inode) 1192 1141 { 1193 - struct file *file = iocb->ki_filp; 1194 - struct inode *inode = file_inode(file); 1195 - ssize_t ret; 1196 - int err; 1197 1142 struct ntfs_inode *ni = ntfs_i(inode); 1198 1143 1199 1144 if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ··· 1201 1152 return -EOPNOTSUPP; 1202 1153 } 1203 1154 1204 - if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { 1205 - ntfs_inode_warn(inode, "direct i/o + compressed not supported"); 1155 + if (is_dedup(ni)) { 1156 + ntfs_inode_warn(inode, "write into deduplicated not supported"); 1206 1157 return -EOPNOTSUPP; 1207 1158 } 1208 1159 1209 - if (is_dedup(ni)) { 1210 - ntfs_inode_warn(inode, "write into deduplicated not supported"); 1160 + return 0; 1161 + } 1162 + 1163 + /* 1164 + * ntfs_file_write_iter - file_operations::write_iter 1165 + */ 1166 + static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 1167 + { 1168 + struct file *file = iocb->ki_filp; 1169 + struct inode *inode = file_inode(file); 1170 + struct ntfs_inode *ni = ntfs_i(inode); 1171 + ssize_t ret; 1172 + int err; 1173 + 1174 + err = check_write_restriction(inode); 1175 + if (err) 1176 + return err; 1177 + 1178 + if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { 1179 + ntfs_inode_warn(inode, "direct i/o + compressed not supported"); 1211 1180 return -EOPNOTSUPP; 1212 1181 } 1213 1182 ··· 1313 1246 /* If we are last writer on the inode, drop the block reservation. */ 1314 1247 if (sbi->options->prealloc && 1315 1248 ((file->f_mode & FMODE_WRITE) && 1316 - atomic_read(&inode->i_writecount) == 1)) { 1249 + atomic_read(&inode->i_writecount) == 1) 1250 + /* 1251 + * The only file when inode->i_fop = &ntfs_file_operations and 1252 + * init_rwsem(&ni->file.run_lock) is not called explicitly is MFT. 1253 + * 1254 + * Add additional check here. 1255 + */ 1256 + && inode->i_ino != MFT_REC_MFT) { 1317 1257 ni_lock(ni); 1318 1258 down_write(&ni->file.run_lock); 1319 1259 ··· 1356 1282 return err; 1357 1283 } 1358 1284 1285 + /* 1286 + * ntfs_file_splice_write - file_operations::splice_write 1287 + */ 1288 + static ssize_t ntfs_file_splice_write(struct pipe_inode_info *pipe, 1289 + struct file *file, loff_t *ppos, 1290 + size_t len, unsigned int flags) 1291 + { 1292 + ssize_t err; 1293 + struct inode *inode = file_inode(file); 1294 + 1295 + err = check_write_restriction(inode); 1296 + if (err) 1297 + return err; 1298 + 1299 + return iter_file_splice_write(pipe, file, ppos, len, flags); 1300 + } 1301 + 1359 1302 // clang-format off 1360 1303 const struct inode_operations ntfs_file_inode_operations = { 1361 1304 .getattr = ntfs_getattr, 1362 - .setattr = ntfs3_setattr, 1305 + .setattr = ntfs_setattr, 1363 1306 .listxattr = ntfs_listxattr, 1364 1307 .get_acl = ntfs_get_acl, 1365 1308 .set_acl = ntfs_set_acl, ··· 1394 1303 .compat_ioctl = ntfs_compat_ioctl, 1395 1304 #endif 1396 1305 .splice_read = ntfs_file_splice_read, 1306 + .splice_write = ntfs_file_splice_write, 1397 1307 .mmap = ntfs_file_mmap, 1398 1308 .open = ntfs_file_open, 1399 1309 .fsync = generic_file_fsync, 1400 - .splice_write = iter_file_splice_write, 1401 1310 .fallocate = ntfs_fallocate, 1402 1311 .release = ntfs_file_release, 1403 1312 };
+83 -14
fs/ntfs3/frecord.c
··· 102 102 { 103 103 struct rb_node *node; 104 104 105 - if (!ni->vfs_inode.i_nlink && ni->mi.mrec && is_rec_inuse(ni->mi.mrec)) 105 + if (!ni->vfs_inode.i_nlink && ni->mi.mrec && 106 + is_rec_inuse(ni->mi.mrec) && 107 + !(ni->mi.sbi->flags & NTFS_FLAGS_LOG_REPLAYING)) 106 108 ni_delete_all(ni); 107 109 108 110 al_destroy(ni); ··· 1902 1900 1903 1901 /* 1904 1902 * fiemap_fill_next_extent_k - a copy of fiemap_fill_next_extent 1905 - * but it accepts kernel address for fi_extents_start 1903 + * but it uses 'fe_k' instead of fieinfo->fi_extents_start 1906 1904 */ 1907 1905 static int fiemap_fill_next_extent_k(struct fiemap_extent_info *fieinfo, 1908 - u64 logical, u64 phys, u64 len, u32 flags) 1906 + struct fiemap_extent *fe_k, u64 logical, 1907 + u64 phys, u64 len, u32 flags) 1909 1908 { 1910 1909 struct fiemap_extent extent; 1911 - struct fiemap_extent __user *dest = fieinfo->fi_extents_start; 1912 1910 1913 1911 /* only count the extents */ 1914 1912 if (fieinfo->fi_extents_max == 0) { ··· 1932 1930 extent.fe_length = len; 1933 1931 extent.fe_flags = flags; 1934 1932 1935 - dest += fieinfo->fi_extents_mapped; 1936 - memcpy(dest, &extent, sizeof(extent)); 1933 + memcpy(fe_k + fieinfo->fi_extents_mapped, &extent, sizeof(extent)); 1937 1934 1938 1935 fieinfo->fi_extents_mapped++; 1939 1936 if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max) ··· 1950 1949 __u64 vbo, __u64 len) 1951 1950 { 1952 1951 int err = 0; 1953 - struct fiemap_extent __user *fe_u = fieinfo->fi_extents_start; 1954 1952 struct fiemap_extent *fe_k = NULL; 1955 1953 struct ntfs_sb_info *sbi = ni->mi.sbi; 1956 1954 u8 cluster_bits = sbi->cluster_bits; ··· 2008 2008 err = -ENOMEM; 2009 2009 goto out; 2010 2010 } 2011 - fieinfo->fi_extents_start = fe_k; 2012 2011 2013 2012 end = vbo + len; 2014 2013 alloc_size = le64_to_cpu(attr->nres.alloc_size); ··· 2097 2098 if (vbo + dlen >= end) 2098 2099 flags |= FIEMAP_EXTENT_LAST; 2099 2100 2100 - err = fiemap_fill_next_extent_k(fieinfo, vbo, lbo, dlen, 2101 - flags); 2101 + err = fiemap_fill_next_extent_k(fieinfo, fe_k, vbo, lbo, 2102 + dlen, flags); 2102 2103 2103 2104 if (err < 0) 2104 2105 break; ··· 2119 2120 if (vbo + bytes >= end) 2120 2121 flags |= FIEMAP_EXTENT_LAST; 2121 2122 2122 - err = fiemap_fill_next_extent_k(fieinfo, vbo, lbo, bytes, 2123 + err = fiemap_fill_next_extent_k(fieinfo, fe_k, vbo, lbo, bytes, 2123 2124 flags); 2124 2125 if (err < 0) 2125 2126 break; ··· 2136 2137 /* 2137 2138 * Copy to user memory out of lock 2138 2139 */ 2139 - if (copy_to_user(fe_u, fe_k, 2140 + if (copy_to_user(fieinfo->fi_extents_start, fe_k, 2140 2141 fieinfo->fi_extents_max * 2141 2142 sizeof(struct fiemap_extent))) { 2142 2143 err = -EFAULT; 2143 2144 } 2144 2145 2145 2146 out: 2146 - /* Restore original pointer. */ 2147 - fieinfo->fi_extents_start = fe_u; 2148 2147 kfree(fe_k); 2149 2148 return err; 2150 2149 } ··· 3451 3454 mark_inode_dirty_sync(inode); 3452 3455 3453 3456 return 0; 3457 + } 3458 + 3459 + /* 3460 + * ni_set_compress 3461 + * 3462 + * Helper for 'ntfs_fileattr_set'. 3463 + * Changes compression for empty files and directories only. 3464 + */ 3465 + int ni_set_compress(struct inode *inode, bool compr) 3466 + { 3467 + int err; 3468 + struct ntfs_inode *ni = ntfs_i(inode); 3469 + struct ATTR_STD_INFO *std; 3470 + const char *bad_inode; 3471 + 3472 + if (is_compressed(ni) == !!compr) 3473 + return 0; 3474 + 3475 + if (is_sparsed(ni)) { 3476 + /* sparse and compress not compatible. */ 3477 + return -EOPNOTSUPP; 3478 + } 3479 + 3480 + if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) { 3481 + /*Skip other inodes. (symlink,fifo,...) */ 3482 + return -EOPNOTSUPP; 3483 + } 3484 + 3485 + bad_inode = NULL; 3486 + 3487 + ni_lock(ni); 3488 + 3489 + std = ni_std(ni); 3490 + if (!std) { 3491 + bad_inode = "no std"; 3492 + goto out; 3493 + } 3494 + 3495 + if (S_ISREG(inode->i_mode)) { 3496 + err = attr_set_compress(ni, compr); 3497 + if (err) { 3498 + if (err == -ENOENT) { 3499 + /* Fix on the fly? */ 3500 + /* Each file must contain data attribute. */ 3501 + bad_inode = "no data attribute"; 3502 + } 3503 + goto out; 3504 + } 3505 + } 3506 + 3507 + ni->std_fa = std->fa; 3508 + if (compr) 3509 + std->fa |= FILE_ATTRIBUTE_COMPRESSED; 3510 + else 3511 + std->fa &= ~FILE_ATTRIBUTE_COMPRESSED; 3512 + 3513 + if (ni->std_fa != std->fa) { 3514 + ni->std_fa = std->fa; 3515 + ni->mi.dirty = true; 3516 + } 3517 + /* update duplicate information and directory entries in ni_write_inode.*/ 3518 + ni->ni_flags |= NI_FLAG_UPDATE_PARENT; 3519 + err = 0; 3520 + 3521 + out: 3522 + ni_unlock(ni); 3523 + if (bad_inode) { 3524 + ntfs_bad_inode(inode, bad_inode); 3525 + err = -EINVAL; 3526 + } 3527 + 3528 + return err; 3454 3529 }
+17 -2
fs/ntfs3/fslog.c
··· 609 609 *head = cpu_to_le16(index); 610 610 } 611 611 612 + /* 613 + * Enumerate restart table. 614 + * 615 + * @t - table to enumerate. 616 + * @c - current enumerated element. 617 + * 618 + * enumeration starts with @c == NULL 619 + * returns next element or NULL 620 + */ 612 621 static inline void *enum_rstbl(struct RESTART_TABLE *t, void *c) 613 622 { 614 623 __le32 *e; 615 624 u32 bprt; 616 - u16 rsize = t ? le16_to_cpu(t->size) : 0; 625 + u16 rsize; 626 + 627 + if (!t) 628 + return NULL; 629 + 630 + rsize = le16_to_cpu(t->size); 617 631 618 632 if (!c) { 619 - if (!t || !t->total) 633 + /* start enumeration. */ 634 + if (!t->total) 620 635 return NULL; 621 636 e = Add2Ptr(t, sizeof(struct RESTART_TABLE)); 622 637 } else {
+14 -6
fs/ntfs3/inode.c
··· 536 536 if (inode->i_state & I_NEW) 537 537 inode = ntfs_read_mft(inode, name, ref); 538 538 else if (ref->seq != ntfs_i(inode)->mi.mrec->seq) { 539 - /* Inode overlaps? */ 540 - _ntfs_bad_inode(inode); 539 + /* 540 + * Sequence number is not expected. 541 + * Looks like inode was reused but caller uses the old reference 542 + */ 543 + iput(inode); 544 + inode = ERR_PTR(-ESTALE); 541 545 } 542 546 543 - if (IS_ERR(inode) && name) 547 + if (IS_ERR(inode)) 544 548 ntfs_set_state(sb->s_fs_info, NTFS_DIRTY_ERROR); 545 549 546 550 return inode; ··· 609 605 610 606 bytes = ((u64)len << cluster_bits) - off; 611 607 612 - if (lcn == SPARSE_LCN) { 608 + if (lcn >= sbi->used.bitmap.nbits) { 609 + /* This case includes resident/compressed/sparse. */ 613 610 if (!create) { 614 611 if (bh->b_size > bytes) 615 612 bh->b_size = bytes; ··· 1677 1672 attr = ni_find_attr(ni, NULL, NULL, ATTR_EA, NULL, 0, NULL, NULL); 1678 1673 if (attr && attr->non_res) { 1679 1674 /* Delete ATTR_EA, if non-resident. */ 1680 - attr_set_size(ni, ATTR_EA, NULL, 0, NULL, 0, NULL, false, NULL); 1675 + struct runs_tree run; 1676 + run_init(&run); 1677 + attr_set_size(ni, ATTR_EA, NULL, 0, &run, 0, NULL, false, NULL); 1678 + run_close(&run); 1681 1679 } 1682 1680 1683 1681 if (rp_inserted) ··· 2084 2076 // clang-format off 2085 2077 const struct inode_operations ntfs_link_inode_operations = { 2086 2078 .get_link = ntfs_get_link, 2087 - .setattr = ntfs3_setattr, 2079 + .setattr = ntfs_setattr, 2088 2080 .listxattr = ntfs_listxattr, 2089 2081 }; 2090 2082
+1 -2
fs/ntfs3/lib/lzx_decompress.c
··· 512 512 * the same code. (For R0, the swap is a no-op.) 513 513 */ 514 514 match_offset = recent_offsets[offset_slot]; 515 - recent_offsets[offset_slot] = recent_offsets[0]; 516 - recent_offsets[0] = match_offset; 515 + swap(recent_offsets[offset_slot], recent_offsets[0]); 517 516 } else { 518 517 /* Explicit offset */ 519 518
+3
fs/ntfs3/lznt.c
··· 236 236 237 237 /* Do decompression until pointers are inside range. */ 238 238 while (up < unc_end && cmpr < cmpr_end) { 239 + // return err if more than LZNT_CHUNK_SIZE bytes are written 240 + if (up - unc > LZNT_CHUNK_SIZE) 241 + return -EINVAL; 239 242 /* Correct index */ 240 243 while (unc + s_max_off[index] < up) 241 244 index += 1;
+5 -5
fs/ntfs3/namei.c
··· 81 81 if (err < 0) 82 82 inode = ERR_PTR(err); 83 83 else { 84 - ni_lock(ni); 84 + ni_lock_dir(ni); 85 85 inode = dir_search_u(dir, uni, NULL); 86 86 ni_unlock(ni); 87 87 } ··· 395 395 /* 396 396 * Try slow way with current upcase table 397 397 */ 398 - uni = __getname(); 398 + uni = kmem_cache_alloc(names_cachep, GFP_NOWAIT); 399 399 if (!uni) 400 400 return -ENOMEM; 401 401 ··· 417 417 err = 0; 418 418 419 419 out: 420 - __putname(uni); 420 + kmem_cache_free(names_cachep, uni); 421 421 return err; 422 422 } 423 423 ··· 503 503 .rename = ntfs_rename, 504 504 .get_acl = ntfs_get_acl, 505 505 .set_acl = ntfs_set_acl, 506 - .setattr = ntfs3_setattr, 506 + .setattr = ntfs_setattr, 507 507 .getattr = ntfs_getattr, 508 508 .listxattr = ntfs_listxattr, 509 509 .fiemap = ntfs_fiemap, ··· 512 512 }; 513 513 514 514 const struct inode_operations ntfs_special_inode_operations = { 515 - .setattr = ntfs3_setattr, 515 + .setattr = ntfs_setattr, 516 516 .getattr = ntfs_getattr, 517 517 .listxattr = ntfs_listxattr, 518 518 .get_acl = ntfs_get_acl,
+5 -5
fs/ntfs3/ntfs_fs.h
··· 334 334 335 335 /* Nested class for ntfs_inode::ni_lock. */ 336 336 enum ntfs_inode_mutex_lock_class { 337 - NTFS_INODE_MUTEX_DIRTY, 337 + NTFS_INODE_MUTEX_DIRTY = 1, 338 338 NTFS_INODE_MUTEX_SECURITY, 339 339 NTFS_INODE_MUTEX_OBJID, 340 340 NTFS_INODE_MUTEX_REPARSE, ··· 453 453 int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes); 454 454 int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size); 455 455 int attr_force_nonresident(struct ntfs_inode *ni); 456 + int attr_set_compress(struct ntfs_inode *ni, bool compr); 456 457 457 458 /* Functions from attrlist.c */ 458 459 void al_destroy(struct ntfs_inode *ni); ··· 472 471 u8 name_len, CLST svcn, __le16 id, const struct MFT_REF *ref, 473 472 struct ATTR_LIST_ENTRY **new_le); 474 473 bool al_remove_le(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le); 475 - bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn, 476 - const __le16 *name, u8 name_len, const struct MFT_REF *ref); 477 474 int al_update(struct ntfs_inode *ni, int sync); 478 475 static inline size_t al_aligned(size_t size) 479 476 { ··· 501 502 struct fileattr *fa); 502 503 int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path, 503 504 struct kstat *stat, u32 request_mask, u32 flags); 504 - int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 505 - struct iattr *attr); 505 + int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 506 + struct iattr *attr); 506 507 int ntfs_file_open(struct inode *inode, struct file *file); 507 508 int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 508 509 __u64 start, __u64 len); ··· 587 588 bool *is_bad); 588 589 589 590 bool ni_is_dirty(struct inode *inode); 591 + int ni_set_compress(struct inode *inode, bool compr); 590 592 591 593 /* Globals from fslog.c */ 592 594 bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes);
+15 -16
fs/ntfs3/record.c
··· 223 223 prev_type = 0; 224 224 attr = Add2Ptr(rec, off); 225 225 } else { 226 - /* Check if input attr inside record. */ 226 + /* 227 + * We don't need to check previous attr here. There is 228 + * a bounds checking in the previous round. 229 + */ 227 230 off = PtrOffset(rec, attr); 228 - if (off >= used) 229 - return NULL; 230 231 231 232 asize = le32_to_cpu(attr->size); 232 - if (asize < SIZEOF_RESIDENT) { 233 - /* Impossible 'cause we should not return such attribute. */ 234 - return NULL; 235 - } 236 - 237 - /* Overflow check. */ 238 - if (off + asize < off) 239 - return NULL; 240 233 241 234 prev_type = le32_to_cpu(attr->type); 242 235 attr = Add2Ptr(attr, asize); 243 236 off += asize; 244 237 } 245 238 246 - asize = le32_to_cpu(attr->size); 247 - 248 239 /* Can we use the first field (attr->type). */ 240 + /* NOTE: this code also checks attr->size availability. */ 249 241 if (off + 8 > used) { 250 242 static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8); 251 243 return NULL; ··· 256 264 /* attributes in record must be ordered by type */ 257 265 if (t32 < prev_type) 258 266 return NULL; 267 + 268 + asize = le32_to_cpu(attr->size); 259 269 260 270 /* Check overflow and boundary. */ 261 271 if (off + asize < off || off + asize > used) ··· 287 293 if (attr->non_res != 1) 288 294 return NULL; 289 295 296 + /* Can we use memory including attr->nres.valid_size? */ 297 + if (asize < SIZEOF_NONRESIDENT) 298 + return NULL; 299 + 290 300 t16 = le16_to_cpu(attr->nres.run_off); 291 301 if (t16 > asize) 292 302 return NULL; ··· 317 319 318 320 if (!attr->nres.svcn && is_attr_ext(attr)) { 319 321 /* First segment of sparse/compressed attribute */ 320 - if (asize + 8 < SIZEOF_NONRESIDENT_EX) 322 + /* Can we use memory including attr->nres.total_size? */ 323 + if (asize < SIZEOF_NONRESIDENT_EX) 321 324 return NULL; 322 325 323 326 tot_size = le64_to_cpu(attr->nres.total_size); ··· 328 329 if (tot_size > alloc_size) 329 330 return NULL; 330 331 } else { 331 - if (asize + 8 < SIZEOF_NONRESIDENT) 332 + if (attr->nres.c_unit) 332 333 return NULL; 333 334 334 - if (attr->nres.c_unit) 335 + if (alloc_size > mi->sbi->volume.size) 335 336 return NULL; 336 337 } 337 338
+5 -3
fs/ntfs3/run.c
··· 959 959 * Large positive number requires to store 5 bytes 960 960 * e.g.: 05 FF 7E FF FF 00 00 00 961 961 */ 962 - if (size_size > 8) 962 + if (size_size > sizeof(len)) 963 963 return -EINVAL; 964 964 965 965 len = run_unpack_s64(run_buf, size_size, 0); ··· 971 971 972 972 if (!offset_size) 973 973 lcn = SPARSE_LCN64; 974 - else if (offset_size <= 8) { 974 + else if (offset_size <= sizeof(s64)) { 975 975 s64 dlcn; 976 976 977 977 /* Initial value of dlcn is -1 or 0. */ ··· 984 984 return -EINVAL; 985 985 lcn = prev_lcn + dlcn; 986 986 prev_lcn = lcn; 987 - } else 987 + } else { 988 + /* The size of 'dlcn' can't be > 8. */ 988 989 return -EINVAL; 990 + } 989 991 990 992 next_vcn = vcn64 + len; 991 993 /* Check boundary. */
+37 -33
fs/ntfs3/super.c
··· 90 90 level = printk_get_level(fmt); 91 91 vaf.fmt = printk_skip_level(fmt); 92 92 vaf.va = &args; 93 - printk("%c%cntfs3: %s: %pV\n", KERN_SOH_ASCII, level, sb->s_id, &vaf); 93 + printk("%c%cntfs3(%s): %pV\n", KERN_SOH_ASCII, level, sb->s_id, &vaf); 94 94 95 95 va_end(args); 96 96 } ··· 124 124 struct dentry *de = d_find_alias(inode); 125 125 126 126 if (de) { 127 + int len; 127 128 spin_lock(&de->d_lock); 128 - snprintf(name, sizeof(s_name_buf), " \"%s\"", 129 - de->d_name.name); 129 + len = snprintf(name, sizeof(s_name_buf), " \"%s\"", 130 + de->d_name.name); 130 131 spin_unlock(&de->d_lock); 132 + if (len <= 0) 133 + name[0] = 0; 134 + else if (len >= sizeof(s_name_buf)) 135 + name[sizeof(s_name_buf) - 1] = 0; 131 136 } else { 132 137 name[0] = 0; 133 138 } ··· 145 140 vaf.fmt = printk_skip_level(fmt); 146 141 vaf.va = &args; 147 142 148 - printk("%c%cntfs3: %s: ino=%lx,%s %pV\n", KERN_SOH_ASCII, level, 143 + printk("%c%cntfs3(%s): ino=%lx,%s %pV\n", KERN_SOH_ASCII, level, 149 144 sb->s_id, inode->i_ino, name ? name : "", &vaf); 150 145 151 146 va_end(args); ··· 264 259 265 260 // clang-format off 266 261 static const struct fs_parameter_spec ntfs_fs_parameters[] = { 267 - fsparam_uid("uid", Opt_uid), 268 - fsparam_gid("gid", Opt_gid), 269 - fsparam_u32oct("umask", Opt_umask), 270 - fsparam_u32oct("dmask", Opt_dmask), 271 - fsparam_u32oct("fmask", Opt_fmask), 272 - fsparam_flag_no("sys_immutable", Opt_immutable), 273 - fsparam_flag_no("discard", Opt_discard), 274 - fsparam_flag_no("force", Opt_force), 275 - fsparam_flag_no("sparse", Opt_sparse), 276 - fsparam_flag_no("hidden", Opt_nohidden), 277 - fsparam_flag_no("hide_dot_files", Opt_hide_dot_files), 278 - fsparam_flag_no("windows_names", Opt_windows_names), 279 - fsparam_flag_no("showmeta", Opt_showmeta), 280 - fsparam_flag_no("acl", Opt_acl), 281 - fsparam_string("iocharset", Opt_iocharset), 282 - fsparam_flag_no("prealloc", Opt_prealloc), 283 - fsparam_flag_no("case", Opt_nocase), 262 + fsparam_uid("uid", Opt_uid), 263 + fsparam_gid("gid", Opt_gid), 264 + fsparam_u32oct("umask", Opt_umask), 265 + fsparam_u32oct("dmask", Opt_dmask), 266 + fsparam_u32oct("fmask", Opt_fmask), 267 + fsparam_flag("sys_immutable", Opt_immutable), 268 + fsparam_flag("discard", Opt_discard), 269 + fsparam_flag("force", Opt_force), 270 + fsparam_flag("sparse", Opt_sparse), 271 + fsparam_flag("nohidden", Opt_nohidden), 272 + fsparam_flag("hide_dot_files", Opt_hide_dot_files), 273 + fsparam_flag("windows_names", Opt_windows_names), 274 + fsparam_flag("showmeta", Opt_showmeta), 275 + fsparam_flag("acl", Opt_acl), 276 + fsparam_string("iocharset", Opt_iocharset), 277 + fsparam_flag("prealloc", Opt_prealloc), 278 + fsparam_flag("nocase", Opt_nocase), 284 279 {} 285 280 }; 286 281 // clang-format on ··· 350 345 opts->fmask = 1; 351 346 break; 352 347 case Opt_immutable: 353 - opts->sys_immutable = result.negated ? 0 : 1; 348 + opts->sys_immutable = 1; 354 349 break; 355 350 case Opt_discard: 356 - opts->discard = result.negated ? 0 : 1; 351 + opts->discard = 1; 357 352 break; 358 353 case Opt_force: 359 - opts->force = result.negated ? 0 : 1; 354 + opts->force = 1; 360 355 break; 361 356 case Opt_sparse: 362 - opts->sparse = result.negated ? 0 : 1; 357 + opts->sparse = 1; 363 358 break; 364 359 case Opt_nohidden: 365 - opts->nohidden = result.negated ? 1 : 0; 360 + opts->nohidden = 1; 366 361 break; 367 362 case Opt_hide_dot_files: 368 - opts->hide_dot_files = result.negated ? 0 : 1; 363 + opts->hide_dot_files = 1; 369 364 break; 370 365 case Opt_windows_names: 371 - opts->windows_names = result.negated ? 0 : 1; 366 + opts->windows_names = 1; 372 367 break; 373 368 case Opt_showmeta: 374 - opts->showmeta = result.negated ? 0 : 1; 369 + opts->showmeta = 1; 375 370 break; 376 371 case Opt_acl: 377 372 if (!result.negated) ··· 390 385 param->string = NULL; 391 386 break; 392 387 case Opt_prealloc: 393 - opts->prealloc = result.negated ? 0 : 1; 388 + opts->prealloc = 1; 394 389 break; 395 390 case Opt_nocase: 396 - opts->nocase = result.negated ? 1 : 0; 391 + opts->nocase = 1; 397 392 break; 398 393 default: 399 394 /* Should not be here unless we forget add case. */ ··· 1496 1491 1497 1492 #ifdef __BIG_ENDIAN 1498 1493 { 1499 - const __le16 *src = sbi->upcase; 1500 1494 u16 *dst = sbi->upcase; 1501 1495 1502 1496 for (i = 0; i < 0x10000; i++) 1503 - *dst++ = le16_to_cpu(*src++); 1497 + __swab16s(dst++); 1504 1498 } 1505 1499 #endif 1506 1500
+1 -1
fs/ntfs3/xattr.c
··· 705 705 #endif 706 706 707 707 /* 708 - * ntfs_acl_chmod - Helper for ntfs3_setattr(). 708 + * ntfs_acl_chmod - Helper for ntfs_setattr(). 709 709 */ 710 710 int ntfs_acl_chmod(struct mnt_idmap *idmap, struct dentry *dentry) 711 711 {