mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ntfs: fix lookup of POSIX names with Windows-invalid characters
POSIX FILE_NAME entries may contain characters such as '?' that are invalid in the Windows namespace. Directory index lookup currently passes an invalid-character error value to ntfs_collate_names(), causing lookup and removal of such names to fail with -EINVAL. Allow callers to disable invalid-character errors when collation is used for index traversal, and suppress those errors when comparing POSIX FILE_NAME attributes. Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Tested-by: Baolin Liu <liubaolin@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
418452b43d
commit
351bdddcc0
|
|
@ -909,7 +909,7 @@ static int ntfs_attr_find(const __le32 type, const __le16 *name,
|
|||
|
||||
rc = ntfs_collate_names(name, name_len,
|
||||
(__le16 *)((u8 *)a + le16_to_cpu(a->name_offset)),
|
||||
a->name_length, 1, IGNORE_CASE,
|
||||
a->name_length, true, IGNORE_CASE,
|
||||
upcase, upcase_len);
|
||||
/*
|
||||
* If @name collates before a->name, there is no
|
||||
|
|
@ -922,7 +922,7 @@ static int ntfs_attr_find(const __le32 type, const __le16 *name,
|
|||
continue;
|
||||
rc = ntfs_collate_names(name, name_len,
|
||||
(__le16 *)((u8 *)a + le16_to_cpu(a->name_offset)),
|
||||
a->name_length, 1, CASE_SENSITIVE,
|
||||
a->name_length, true, CASE_SENSITIVE,
|
||||
upcase, upcase_len);
|
||||
if (rc == -1)
|
||||
return -ENOENT;
|
||||
|
|
@ -1313,7 +1313,7 @@ static int ntfs_external_attr_find(const __le32 type,
|
|||
register int rc;
|
||||
|
||||
rc = ntfs_collate_names(name, name_len, al_name,
|
||||
al_name_len, 1, IGNORE_CASE,
|
||||
al_name_len, true, IGNORE_CASE,
|
||||
vol->upcase, vol->upcase_len);
|
||||
/*
|
||||
* If @name collates before al_name, there is no
|
||||
|
|
@ -1326,7 +1326,7 @@ static int ntfs_external_attr_find(const __le32 type,
|
|||
continue;
|
||||
|
||||
rc = ntfs_collate_names(name, name_len, al_name,
|
||||
al_name_len, 1, CASE_SENSITIVE,
|
||||
al_name_len, true, CASE_SENSITIVE,
|
||||
vol->upcase, vol->upcase_len);
|
||||
if (rc == -1)
|
||||
goto not_found;
|
||||
|
|
|
|||
|
|
@ -100,11 +100,11 @@ static int ntfs_collate_file_name(struct ntfs_volume *vol,
|
|||
{
|
||||
int rc;
|
||||
|
||||
rc = ntfs_file_compare_values(data1, data2, -EINVAL,
|
||||
IGNORE_CASE, vol->upcase, vol->upcase_len);
|
||||
rc = ntfs_file_compare_values(data1, data2,
|
||||
true, IGNORE_CASE, vol->upcase, vol->upcase_len);
|
||||
if (!rc)
|
||||
rc = ntfs_file_compare_values(data1, data2,
|
||||
-EINVAL, CASE_SENSITIVE, vol->upcase, vol->upcase_len);
|
||||
true, CASE_SENSITIVE, vol->upcase, vol->upcase_len);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ u64 ntfs_lookup_inode_by_name(struct ntfs_inode *dir_ni, const __le16 *uname,
|
|||
*/
|
||||
rc = ntfs_collate_names(uname, uname_len,
|
||||
(__le16 *)&ie->key.file_name.file_name,
|
||||
ie->key.file_name.file_name_length, 1,
|
||||
ie->key.file_name.file_name_length, false,
|
||||
IGNORE_CASE, vol->upcase, vol->upcase_len);
|
||||
/*
|
||||
* If uname collates before the name of the current entry, there
|
||||
|
|
@ -257,7 +257,7 @@ u64 ntfs_lookup_inode_by_name(struct ntfs_inode *dir_ni, const __le16 *uname,
|
|||
*/
|
||||
rc = ntfs_collate_names(uname, uname_len,
|
||||
(__le16 *)&ie->key.file_name.file_name,
|
||||
ie->key.file_name.file_name_length, 1,
|
||||
ie->key.file_name.file_name_length, false,
|
||||
CASE_SENSITIVE, vol->upcase, vol->upcase_len);
|
||||
if (rc == -1)
|
||||
break;
|
||||
|
|
@ -474,7 +474,7 @@ u64 ntfs_lookup_inode_by_name(struct ntfs_inode *dir_ni, const __le16 *uname,
|
|||
*/
|
||||
rc = ntfs_collate_names(uname, uname_len,
|
||||
(__le16 *)&ie->key.file_name.file_name,
|
||||
ie->key.file_name.file_name_length, 1,
|
||||
ie->key.file_name.file_name_length, false,
|
||||
IGNORE_CASE, vol->upcase, vol->upcase_len);
|
||||
/*
|
||||
* If uname collates before the name of the current entry, there
|
||||
|
|
@ -493,7 +493,7 @@ u64 ntfs_lookup_inode_by_name(struct ntfs_inode *dir_ni, const __le16 *uname,
|
|||
*/
|
||||
rc = ntfs_collate_names(uname, uname_len,
|
||||
(__le16 *)&ie->key.file_name.file_name,
|
||||
ie->key.file_name.file_name_length, 1,
|
||||
ie->key.file_name.file_name_length, false,
|
||||
CASE_SENSITIVE, vol->upcase, vol->upcase_len);
|
||||
if (rc == -1)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -234,14 +234,14 @@ bool ntfs_are_names_equal(const __le16 *s1, size_t s1_len,
|
|||
const __le16 *upcase, const u32 upcase_size);
|
||||
int ntfs_collate_names(const __le16 *name1, const u32 name1_len,
|
||||
const __le16 *name2, const u32 name2_len,
|
||||
const int err_val, const u32 ic,
|
||||
const bool check_invalid, const u32 ic,
|
||||
const __le16 *upcase, const u32 upcase_len);
|
||||
int ntfs_ucsncmp(const __le16 *s1, const __le16 *s2, size_t n);
|
||||
int ntfs_ucsncasecmp(const __le16 *s1, const __le16 *s2, size_t n,
|
||||
const __le16 *upcase, const u32 upcase_size);
|
||||
int ntfs_file_compare_values(const struct file_name_attr *file_name_attr1,
|
||||
const struct file_name_attr *file_name_attr2,
|
||||
const int err_val, const u32 ic,
|
||||
const bool check_invalid, const u32 ic,
|
||||
const __le16 *upcase, const u32 upcase_len);
|
||||
int ntfs_nlstoucs(const struct ntfs_volume *vol, const char *ins,
|
||||
const int ins_len, __le16 **outs, int max_name_len);
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ bool ntfs_are_names_equal(const __le16 *s1, size_t s1_len,
|
|||
* @name1_len: first Unicode name length
|
||||
* @name2: second Unicode name to compare
|
||||
* @name2_len: second Unicode name length
|
||||
* @err_val: if @name1 contains an invalid character return this value
|
||||
* @check_invalid: if true and @name1 contains an invalid character,
|
||||
* return -EINVAL
|
||||
* @ic: either CASE_SENSITIVE or IGNORE_CASE
|
||||
* @upcase: upcase table (ignored if @ic is CASE_SENSITIVE)
|
||||
* @upcase_len: upcase table size (ignored if @ic is CASE_SENSITIVE)
|
||||
|
|
@ -74,13 +75,14 @@ bool ntfs_are_names_equal(const __le16 *s1, size_t s1_len,
|
|||
* -1 if the first name collates before the second one,
|
||||
* 0 if the names match,
|
||||
* 1 if the second name collates before the first one, or
|
||||
* @err_val if an invalid character is found in @name1 during the comparison.
|
||||
* -EINVAL if @check_invalid is true and an invalid character is found in
|
||||
* @name1 during the comparison.
|
||||
*
|
||||
* The following characters are considered invalid: '"', '*', '<', '>' and '?'.
|
||||
*/
|
||||
int ntfs_collate_names(const __le16 *name1, const u32 name1_len,
|
||||
const __le16 *name2, const u32 name2_len,
|
||||
const int err_val, const u32 ic,
|
||||
const bool check_invalid, const u32 ic,
|
||||
const __le16 *upcase, const u32 upcase_len)
|
||||
{
|
||||
u32 cnt, min_len;
|
||||
|
|
@ -98,8 +100,8 @@ int ntfs_collate_names(const __le16 *name1, const u32 name1_len,
|
|||
if (c2 < upcase_len)
|
||||
c2 = le16_to_cpu(upcase[c2]);
|
||||
}
|
||||
if (c1 < 64 && legal_ansi_char_array[c1] & 8)
|
||||
return err_val;
|
||||
if (check_invalid && c1 < 64 && legal_ansi_char_array[c1] & 8)
|
||||
return -EINVAL;
|
||||
if (c1 < c2)
|
||||
return -1;
|
||||
if (c1 > c2)
|
||||
|
|
@ -111,8 +113,8 @@ int ntfs_collate_names(const __le16 *name1, const u32 name1_len,
|
|||
return 0;
|
||||
/* name1_len > name2_len */
|
||||
c1 = le16_to_cpu(*name1);
|
||||
if (c1 < 64 && legal_ansi_char_array[c1] & 8)
|
||||
return err_val;
|
||||
if (check_invalid && c1 < 64 && legal_ansi_char_array[c1] & 8)
|
||||
return -EINVAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -191,14 +193,23 @@ int ntfs_ucsncasecmp(const __le16 *s1, const __le16 *s2, size_t n,
|
|||
|
||||
int ntfs_file_compare_values(const struct file_name_attr *file_name_attr1,
|
||||
const struct file_name_attr *file_name_attr2,
|
||||
const int err_val, const u32 ic,
|
||||
const bool check_invalid, const u32 ic,
|
||||
const __le16 *upcase, const u32 upcase_len)
|
||||
{
|
||||
bool compare_check = check_invalid;
|
||||
|
||||
/*
|
||||
* POSIX file names may contain characters that are invalid in the
|
||||
* Windows namespace, so compare them without treating them as errors.
|
||||
*/
|
||||
if (file_name_attr1->file_name_type == FILE_NAME_POSIX)
|
||||
compare_check = false;
|
||||
|
||||
return ntfs_collate_names((__le16 *)&file_name_attr1->file_name,
|
||||
file_name_attr1->file_name_length,
|
||||
(__le16 *)&file_name_attr2->file_name,
|
||||
file_name_attr2->file_name_length,
|
||||
err_val, ic, upcase, upcase_len);
|
||||
compare_check, ic, upcase, upcase_len);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user