diff options
Diffstat (limited to 'fs/vfat/namei.c')
-rw-r--r-- | fs/vfat/namei.c | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index cd450bea9f1a..a3522727ea5b 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c | |||
@@ -176,15 +176,10 @@ static inline int vfat_is_used_badchars(const wchar_t *s, int len) | |||
176 | for (i = 0; i < len; i++) | 176 | for (i = 0; i < len; i++) |
177 | if (vfat_bad_char(s[i])) | 177 | if (vfat_bad_char(s[i])) |
178 | return -EINVAL; | 178 | return -EINVAL; |
179 | return 0; | ||
180 | } | ||
181 | 179 | ||
182 | static int vfat_valid_longname(const unsigned char *name, unsigned int len) | 180 | if (s[i - 1] == ' ') /* last character cannot be space */ |
183 | { | ||
184 | if (name[len - 1] == ' ') | ||
185 | return -EINVAL; | 181 | return -EINVAL; |
186 | if (len >= 256) | 182 | |
187 | return -ENAMETOOLONG; | ||
188 | return 0; | 183 | return 0; |
189 | } | 184 | } |
190 | 185 | ||
@@ -477,7 +472,7 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, | |||
477 | if (utf8) { | 472 | if (utf8) { |
478 | int name_len = strlen(name); | 473 | int name_len = strlen(name); |
479 | 474 | ||
480 | *outlen = utf8_mbstowcs((wchar_t *)outname, name, PAGE_SIZE); | 475 | *outlen = utf8_mbstowcs((wchar_t *)outname, name, PATH_MAX); |
481 | 476 | ||
482 | /* | 477 | /* |
483 | * We stripped '.'s before and set len appropriately, | 478 | * We stripped '.'s before and set len appropriately, |
@@ -485,11 +480,14 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, | |||
485 | */ | 480 | */ |
486 | *outlen -= (name_len - len); | 481 | *outlen -= (name_len - len); |
487 | 482 | ||
483 | if (*outlen > 255) | ||
484 | return -ENAMETOOLONG; | ||
485 | |||
488 | op = &outname[*outlen * sizeof(wchar_t)]; | 486 | op = &outname[*outlen * sizeof(wchar_t)]; |
489 | } else { | 487 | } else { |
490 | if (nls) { | 488 | if (nls) { |
491 | for (i = 0, ip = name, op = outname, *outlen = 0; | 489 | for (i = 0, ip = name, op = outname, *outlen = 0; |
492 | i < len && *outlen <= 260; | 490 | i < len && *outlen <= 255; |
493 | *outlen += 1) | 491 | *outlen += 1) |
494 | { | 492 | { |
495 | if (escape && (*ip == ':')) { | 493 | if (escape && (*ip == ':')) { |
@@ -525,18 +523,20 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, | |||
525 | op += 2; | 523 | op += 2; |
526 | } | 524 | } |
527 | } | 525 | } |
526 | if (i < len) | ||
527 | return -ENAMETOOLONG; | ||
528 | } else { | 528 | } else { |
529 | for (i = 0, ip = name, op = outname, *outlen = 0; | 529 | for (i = 0, ip = name, op = outname, *outlen = 0; |
530 | i < len && *outlen <= 260; | 530 | i < len && *outlen <= 255; |
531 | i++, *outlen += 1) | 531 | i++, *outlen += 1) |
532 | { | 532 | { |
533 | *op++ = *ip++; | 533 | *op++ = *ip++; |
534 | *op++ = 0; | 534 | *op++ = 0; |
535 | } | 535 | } |
536 | if (i < len) | ||
537 | return -ENAMETOOLONG; | ||
536 | } | 538 | } |
537 | } | 539 | } |
538 | if (*outlen > 260) | ||
539 | return -ENAMETOOLONG; | ||
540 | 540 | ||
541 | *longlen = *outlen; | 541 | *longlen = *outlen; |
542 | if (*outlen % 13) { | 542 | if (*outlen % 13) { |
@@ -565,7 +565,6 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name, | |||
565 | struct fat_mount_options *opts = &sbi->options; | 565 | struct fat_mount_options *opts = &sbi->options; |
566 | struct msdos_dir_slot *ps; | 566 | struct msdos_dir_slot *ps; |
567 | struct msdos_dir_entry *de; | 567 | struct msdos_dir_entry *de; |
568 | unsigned long page; | ||
569 | unsigned char cksum, lcase; | 568 | unsigned char cksum, lcase; |
570 | unsigned char msdos_name[MSDOS_NAME]; | 569 | unsigned char msdos_name[MSDOS_NAME]; |
571 | wchar_t *uname; | 570 | wchar_t *uname; |
@@ -574,15 +573,11 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name, | |||
574 | loff_t offset; | 573 | loff_t offset; |
575 | 574 | ||
576 | *nr_slots = 0; | 575 | *nr_slots = 0; |
577 | err = vfat_valid_longname(name, len); | ||
578 | if (err) | ||
579 | return err; | ||
580 | 576 | ||
581 | page = __get_free_page(GFP_KERNEL); | 577 | uname = __getname(); |
582 | if (!page) | 578 | if (!uname) |
583 | return -ENOMEM; | 579 | return -ENOMEM; |
584 | 580 | ||
585 | uname = (wchar_t *)page; | ||
586 | err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize, | 581 | err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize, |
587 | opts->unicode_xlate, opts->utf8, sbi->nls_io); | 582 | opts->unicode_xlate, opts->utf8, sbi->nls_io); |
588 | if (err) | 583 | if (err) |
@@ -634,7 +629,7 @@ shortname: | |||
634 | de->starthi = cpu_to_le16(cluster >> 16); | 629 | de->starthi = cpu_to_le16(cluster >> 16); |
635 | de->size = 0; | 630 | de->size = 0; |
636 | out_free: | 631 | out_free: |
637 | free_page(page); | 632 | __putname(uname); |
638 | return err; | 633 | return err; |
639 | } | 634 | } |
640 | 635 | ||
@@ -991,7 +986,7 @@ error_inode: | |||
991 | if (corrupt < 0) { | 986 | if (corrupt < 0) { |
992 | fat_fs_panic(new_dir->i_sb, | 987 | fat_fs_panic(new_dir->i_sb, |
993 | "%s: Filesystem corrupted (i_pos %lld)", | 988 | "%s: Filesystem corrupted (i_pos %lld)", |
994 | __FUNCTION__, sinfo.i_pos); | 989 | __func__, sinfo.i_pos); |
995 | } | 990 | } |
996 | goto out; | 991 | goto out; |
997 | } | 992 | } |
@@ -1003,7 +998,7 @@ static const struct inode_operations vfat_dir_inode_operations = { | |||
1003 | .mkdir = vfat_mkdir, | 998 | .mkdir = vfat_mkdir, |
1004 | .rmdir = vfat_rmdir, | 999 | .rmdir = vfat_rmdir, |
1005 | .rename = vfat_rename, | 1000 | .rename = vfat_rename, |
1006 | .setattr = fat_notify_change, | 1001 | .setattr = fat_setattr, |
1007 | .getattr = fat_getattr, | 1002 | .getattr = fat_getattr, |
1008 | }; | 1003 | }; |
1009 | 1004 | ||