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

exfat: handle unreconized benign secondary entries

Sony PXW-Z280 camera add vendor allocation entries to directory of
pictures. Currently, linux exfat does not support it and the file is
not visible. This patch handle vendor extension and allocation entries
as unreconized benign secondary entries. As described in the specification,
it is recognized but ignored, and when deleting directory entry set,
the associated clusters allocation are removed as well as benign secondary
directory entries.

Reported-by: Barócsi Dénes <admin@tveger.hu>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>

+81 -25
+58 -25
fs/exfat/dir.c
··· 29 29 30 30 } 31 31 32 - static void exfat_get_uniname_from_ext_entry(struct super_block *sb, 32 + static int exfat_get_uniname_from_ext_entry(struct super_block *sb, 33 33 struct exfat_chain *p_dir, int entry, unsigned short *uniname) 34 34 { 35 - int i; 35 + int i, err; 36 36 struct exfat_entry_set_cache es; 37 37 38 - if (exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES)) 39 - return; 38 + err = exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES); 39 + if (err) 40 + return err; 40 41 41 42 /* 42 43 * First entry : file entry ··· 57 56 } 58 57 59 58 exfat_put_dentry_set(&es, false); 59 + return 0; 60 60 } 61 61 62 62 /* read a directory entry from the opened directory */ 63 63 static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_entry *dir_entry) 64 64 { 65 - int i, dentries_per_clu, num_ext; 65 + int i, dentries_per_clu, num_ext, err; 66 66 unsigned int type, clu_offset, max_dentries; 67 67 struct exfat_chain dir, clu; 68 68 struct exfat_uni_name uni_name; ··· 148 146 0); 149 147 150 148 *uni_name.name = 0x0; 151 - exfat_get_uniname_from_ext_entry(sb, &clu, i, 149 + err = exfat_get_uniname_from_ext_entry(sb, &clu, i, 152 150 uni_name.name); 151 + if (err) { 152 + brelse(bh); 153 + continue; 154 + } 153 155 exfat_utf16_to_nls(sb, &uni_name, 154 156 dir_entry->namebuf.lfn, 155 157 dir_entry->namebuf.lfnbuf_len); ··· 381 375 return TYPE_ACL; 382 376 return TYPE_CRITICAL_SEC; 383 377 } 378 + 379 + if (ep->type == EXFAT_VENDOR_EXT) 380 + return TYPE_VENDOR_EXT; 381 + if (ep->type == EXFAT_VENDOR_ALLOC) 382 + return TYPE_VENDOR_ALLOC; 383 + 384 384 return TYPE_BENIGN_SEC; 385 385 } 386 386 ··· 530 518 return ret; 531 519 } 532 520 521 + static void exfat_free_benign_secondary_clusters(struct inode *inode, 522 + struct exfat_dentry *ep) 523 + { 524 + struct super_block *sb = inode->i_sb; 525 + struct exfat_chain dir; 526 + unsigned int start_clu = 527 + le32_to_cpu(ep->dentry.generic_secondary.start_clu); 528 + u64 size = le64_to_cpu(ep->dentry.generic_secondary.size); 529 + unsigned char flags = ep->dentry.generic_secondary.flags; 530 + 531 + if (!(flags & ALLOC_POSSIBLE) || !start_clu || !size) 532 + return; 533 + 534 + exfat_chain_set(&dir, start_clu, 535 + EXFAT_B_TO_CLU_ROUND_UP(size, EXFAT_SB(sb)), 536 + flags); 537 + exfat_free_cluster(inode, &dir); 538 + } 539 + 533 540 int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir, 534 541 int entry, int num_entries, struct exfat_uni_name *p_uniname) 535 542 { ··· 581 550 if (!ep) 582 551 return -EIO; 583 552 553 + if (exfat_get_entry_type(ep) & TYPE_BENIGN_SEC) 554 + exfat_free_benign_secondary_clusters(inode, ep); 555 + 584 556 exfat_init_name_entry(ep, uniname); 585 557 exfat_update_bh(bh, sync); 586 558 brelse(bh); ··· 606 572 ep = exfat_get_dentry(sb, p_dir, entry + i, &bh); 607 573 if (!ep) 608 574 return -EIO; 575 + 576 + if (exfat_get_entry_type(ep) & TYPE_BENIGN_SEC) 577 + exfat_free_benign_secondary_clusters(inode, ep); 609 578 610 579 exfat_set_entry_type(ep, TYPE_DELETED); 611 580 exfat_update_bh(bh, IS_DIRSYNC(inode)); ··· 778 741 ES_MODE_GET_STRM_ENTRY, 779 742 ES_MODE_GET_NAME_ENTRY, 780 743 ES_MODE_GET_CRITICAL_SEC_ENTRY, 744 + ES_MODE_GET_BENIGN_SEC_ENTRY, 781 745 }; 782 746 783 747 static bool exfat_validate_entry(unsigned int type, ··· 792 754 if (type != TYPE_FILE && type != TYPE_DIR) 793 755 return false; 794 756 *mode = ES_MODE_GET_FILE_ENTRY; 795 - return true; 757 + break; 796 758 case ES_MODE_GET_FILE_ENTRY: 797 759 if (type != TYPE_STREAM) 798 760 return false; 799 761 *mode = ES_MODE_GET_STRM_ENTRY; 800 - return true; 762 + break; 801 763 case ES_MODE_GET_STRM_ENTRY: 802 764 if (type != TYPE_EXTEND) 803 765 return false; 804 766 *mode = ES_MODE_GET_NAME_ENTRY; 805 - return true; 767 + break; 806 768 case ES_MODE_GET_NAME_ENTRY: 807 - if (type == TYPE_STREAM) 769 + if (type & TYPE_BENIGN_SEC) 770 + *mode = ES_MODE_GET_BENIGN_SEC_ENTRY; 771 + else if (type != TYPE_EXTEND) 808 772 return false; 809 - if (type != TYPE_EXTEND) { 810 - if (!(type & TYPE_CRITICAL_SEC)) 811 - return false; 812 - *mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; 813 - } 814 - return true; 815 - case ES_MODE_GET_CRITICAL_SEC_ENTRY: 816 - if (type == TYPE_EXTEND || type == TYPE_STREAM) 773 + break; 774 + case ES_MODE_GET_BENIGN_SEC_ENTRY: 775 + /* Assume unreconized benign secondary entry */ 776 + if (!(type & TYPE_BENIGN_SEC)) 817 777 return false; 818 - if ((type & TYPE_CRITICAL_SEC) != TYPE_CRITICAL_SEC) 819 - return false; 820 - return true; 778 + break; 821 779 default: 822 - WARN_ON_ONCE(1); 823 780 return false; 824 781 } 782 + 783 + return true; 825 784 } 826 785 827 786 struct exfat_dentry *exfat_get_dentry_cached( ··· 1199 1164 1200 1165 type = exfat_get_entry_type(ext_ep); 1201 1166 brelse(bh); 1202 - if (type == TYPE_EXTEND || type == TYPE_STREAM) 1167 + if (type & TYPE_CRITICAL_SEC || type & TYPE_BENIGN_SEC) 1203 1168 count++; 1204 - else 1205 - break; 1206 1169 } 1207 1170 return count; 1208 1171 }
+2
fs/exfat/exfat_fs.h
··· 71 71 #define TYPE_PADDING 0x0402 72 72 #define TYPE_ACLTAB 0x0403 73 73 #define TYPE_BENIGN_SEC 0x0800 74 + #define TYPE_VENDOR_EXT 0x0801 75 + #define TYPE_VENDOR_ALLOC 0x0802 74 76 75 77 #define MAX_CHARSET_SIZE 6 /* max size of multi-byte character */ 76 78 #define MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */
+21
fs/exfat/exfat_raw.h
··· 27 27 ((sbi)->num_clusters - EXFAT_RESERVED_CLUSTERS) 28 28 29 29 /* AllocationPossible and NoFatChain field in GeneralSecondaryFlags Field */ 30 + #define ALLOC_POSSIBLE 0x01 30 31 #define ALLOC_FAT_CHAIN 0x01 31 32 #define ALLOC_NO_FAT_CHAIN 0x03 32 33 ··· 51 50 #define EXFAT_STREAM 0xC0 /* stream entry */ 52 51 #define EXFAT_NAME 0xC1 /* file name entry */ 53 52 #define EXFAT_ACL 0xC2 /* stream entry */ 53 + #define EXFAT_VENDOR_EXT 0xE0 /* vendor extension entry */ 54 + #define EXFAT_VENDOR_ALLOC 0xE1 /* vendor allocation entry */ 54 55 55 56 #define IS_EXFAT_CRITICAL_PRI(x) (x < 0xA0) 56 57 #define IS_EXFAT_BENIGN_PRI(x) (x < 0xC0) ··· 158 155 __le32 start_clu; 159 156 __le64 size; 160 157 } __packed upcase; /* up-case table directory entry */ 158 + struct { 159 + __u8 flags; 160 + __u8 vendor_guid[16]; 161 + __u8 vendor_defined[14]; 162 + } __packed vendor_ext; /* vendor extension directory entry */ 163 + struct { 164 + __u8 flags; 165 + __u8 vendor_guid[16]; 166 + __u8 vendor_defined[2]; 167 + __le32 start_clu; 168 + __le64 size; 169 + } __packed vendor_alloc; /* vendor allocation directory entry */ 170 + struct { 171 + __u8 flags; 172 + __u8 custom_defined[18]; 173 + __le32 start_clu; 174 + __le64 size; 175 + } __packed generic_secondary; /* generic secondary directory entry */ 161 176 } __packed dentry; 162 177 } __packed; 163 178