diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/udf/dir.c | 3 | ||||
-rw-r--r-- | fs/udf/namei.c | 3 | ||||
-rw-r--r-- | fs/udf/symlink.c | 31 | ||||
-rw-r--r-- | fs/udf/udfdecl.h | 3 | ||||
-rw-r--r-- | fs/udf/unicode.c | 28 |
5 files changed, 48 insertions, 20 deletions
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index a012c51caffd..a7690b46ce0a 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
@@ -167,7 +167,8 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
167 | continue; | 167 | continue; |
168 | } | 168 | } |
169 | 169 | ||
170 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | 170 | flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, |
171 | UDF_NAME_LEN); | ||
171 | if (!flen) | 172 | if (!flen) |
172 | continue; | 173 | continue; |
173 | 174 | ||
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index c12e260fd6c4..6ff19b54b51f 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -233,7 +233,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
233 | if (!lfi) | 233 | if (!lfi) |
234 | continue; | 234 | continue; |
235 | 235 | ||
236 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | 236 | flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, |
237 | UDF_NAME_LEN); | ||
237 | if (flen && udf_match(flen, fname, child->len, child->name)) | 238 | if (flen && udf_match(flen, fname, child->len, child->name)) |
238 | goto out_ok; | 239 | goto out_ok; |
239 | } | 240 | } |
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index c3aa6fafd6cf..0f1b3a2654b9 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c | |||
@@ -30,13 +30,16 @@ | |||
30 | #include <linux/buffer_head.h> | 30 | #include <linux/buffer_head.h> |
31 | #include "udf_i.h" | 31 | #include "udf_i.h" |
32 | 32 | ||
33 | static void udf_pc_to_char(struct super_block *sb, unsigned char *from, | 33 | static int udf_pc_to_char(struct super_block *sb, unsigned char *from, |
34 | int fromlen, unsigned char *to) | 34 | int fromlen, unsigned char *to, int tolen) |
35 | { | 35 | { |
36 | struct pathComponent *pc; | 36 | struct pathComponent *pc; |
37 | int elen = 0; | 37 | int elen = 0; |
38 | int comp_len; | ||
38 | unsigned char *p = to; | 39 | unsigned char *p = to; |
39 | 40 | ||
41 | /* Reserve one byte for terminating \0 */ | ||
42 | tolen--; | ||
40 | while (elen < fromlen) { | 43 | while (elen < fromlen) { |
41 | pc = (struct pathComponent *)(from + elen); | 44 | pc = (struct pathComponent *)(from + elen); |
42 | switch (pc->componentType) { | 45 | switch (pc->componentType) { |
@@ -49,22 +52,37 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from, | |||
49 | break; | 52 | break; |
50 | /* Fall through */ | 53 | /* Fall through */ |
51 | case 2: | 54 | case 2: |
55 | if (tolen == 0) | ||
56 | return -ENAMETOOLONG; | ||
52 | p = to; | 57 | p = to; |
53 | *p++ = '/'; | 58 | *p++ = '/'; |
59 | tolen--; | ||
54 | break; | 60 | break; |
55 | case 3: | 61 | case 3: |
62 | if (tolen < 3) | ||
63 | return -ENAMETOOLONG; | ||
56 | memcpy(p, "../", 3); | 64 | memcpy(p, "../", 3); |
57 | p += 3; | 65 | p += 3; |
66 | tolen -= 3; | ||
58 | break; | 67 | break; |
59 | case 4: | 68 | case 4: |
69 | if (tolen < 2) | ||
70 | return -ENAMETOOLONG; | ||
60 | memcpy(p, "./", 2); | 71 | memcpy(p, "./", 2); |
61 | p += 2; | 72 | p += 2; |
73 | tolen -= 2; | ||
62 | /* that would be . - just ignore */ | 74 | /* that would be . - just ignore */ |
63 | break; | 75 | break; |
64 | case 5: | 76 | case 5: |
65 | p += udf_get_filename(sb, pc->componentIdent, p, | 77 | comp_len = udf_get_filename(sb, pc->componentIdent, |
66 | pc->lengthComponentIdent); | 78 | pc->lengthComponentIdent, |
79 | p, tolen); | ||
80 | p += comp_len; | ||
81 | tolen -= comp_len; | ||
82 | if (tolen == 0) | ||
83 | return -ENAMETOOLONG; | ||
67 | *p++ = '/'; | 84 | *p++ = '/'; |
85 | tolen--; | ||
68 | break; | 86 | break; |
69 | } | 87 | } |
70 | elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; | 88 | elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; |
@@ -73,6 +91,7 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from, | |||
73 | p[-1] = '\0'; | 91 | p[-1] = '\0'; |
74 | else | 92 | else |
75 | p[0] = '\0'; | 93 | p[0] = '\0'; |
94 | return 0; | ||
76 | } | 95 | } |
77 | 96 | ||
78 | static int udf_symlink_filler(struct file *file, struct page *page) | 97 | static int udf_symlink_filler(struct file *file, struct page *page) |
@@ -108,8 +127,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) | |||
108 | symlink = bh->b_data; | 127 | symlink = bh->b_data; |
109 | } | 128 | } |
110 | 129 | ||
111 | udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); | 130 | err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); |
112 | brelse(bh); | 131 | brelse(bh); |
132 | if (err) | ||
133 | goto out_unlock_inode; | ||
113 | 134 | ||
114 | up_read(&iinfo->i_data_sem); | 135 | up_read(&iinfo->i_data_sem); |
115 | SetPageUptodate(page); | 136 | SetPageUptodate(page); |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 1cc3c993ebd0..47bb3f5ca360 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
@@ -211,7 +211,8 @@ udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc, | |||
211 | } | 211 | } |
212 | 212 | ||
213 | /* unicode.c */ | 213 | /* unicode.c */ |
214 | extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); | 214 | extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *, |
215 | int); | ||
215 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, | 216 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, |
216 | int); | 217 | int); |
217 | extern int udf_build_ustr(struct ustr *, dstring *, int); | 218 | extern int udf_build_ustr(struct ustr *, dstring *, int); |
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index afd470e588ff..b84fee372734 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c | |||
@@ -28,7 +28,8 @@ | |||
28 | 28 | ||
29 | #include "udf_sb.h" | 29 | #include "udf_sb.h" |
30 | 30 | ||
31 | static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); | 31 | static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *, |
32 | int); | ||
32 | 33 | ||
33 | static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) | 34 | static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) |
34 | { | 35 | { |
@@ -333,8 +334,8 @@ try_again: | |||
333 | return u_len + 1; | 334 | return u_len + 1; |
334 | } | 335 | } |
335 | 336 | ||
336 | int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | 337 | int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, |
337 | int flen) | 338 | uint8_t *dname, int dlen) |
338 | { | 339 | { |
339 | struct ustr *filename, *unifilename; | 340 | struct ustr *filename, *unifilename; |
340 | int len = 0; | 341 | int len = 0; |
@@ -347,7 +348,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | |||
347 | if (!unifilename) | 348 | if (!unifilename) |
348 | goto out1; | 349 | goto out1; |
349 | 350 | ||
350 | if (udf_build_ustr_exact(unifilename, sname, flen)) | 351 | if (udf_build_ustr_exact(unifilename, sname, slen)) |
351 | goto out2; | 352 | goto out2; |
352 | 353 | ||
353 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { | 354 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { |
@@ -366,7 +367,8 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | |||
366 | } else | 367 | } else |
367 | goto out2; | 368 | goto out2; |
368 | 369 | ||
369 | len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, | 370 | len = udf_translate_to_linux(dname, dlen, |
371 | filename->u_name, filename->u_len, | ||
370 | unifilename->u_name, unifilename->u_len); | 372 | unifilename->u_name, unifilename->u_len); |
371 | out2: | 373 | out2: |
372 | kfree(unifilename); | 374 | kfree(unifilename); |
@@ -403,10 +405,12 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname, | |||
403 | #define EXT_MARK '.' | 405 | #define EXT_MARK '.' |
404 | #define CRC_MARK '#' | 406 | #define CRC_MARK '#' |
405 | #define EXT_SIZE 5 | 407 | #define EXT_SIZE 5 |
408 | /* Number of chars we need to store generated CRC to make filename unique */ | ||
409 | #define CRC_LEN 5 | ||
406 | 410 | ||
407 | static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | 411 | static int udf_translate_to_linux(uint8_t *newName, int newLen, |
408 | int udfLen, uint8_t *fidName, | 412 | uint8_t *udfName, int udfLen, |
409 | int fidNameLen) | 413 | uint8_t *fidName, int fidNameLen) |
410 | { | 414 | { |
411 | int index, newIndex = 0, needsCRC = 0; | 415 | int index, newIndex = 0, needsCRC = 0; |
412 | int extIndex = 0, newExtIndex = 0, hasExt = 0; | 416 | int extIndex = 0, newExtIndex = 0, hasExt = 0; |
@@ -439,7 +443,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | |||
439 | newExtIndex = newIndex; | 443 | newExtIndex = newIndex; |
440 | } | 444 | } |
441 | } | 445 | } |
442 | if (newIndex < 256) | 446 | if (newIndex < newLen) |
443 | newName[newIndex++] = curr; | 447 | newName[newIndex++] = curr; |
444 | else | 448 | else |
445 | needsCRC = 1; | 449 | needsCRC = 1; |
@@ -467,13 +471,13 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | |||
467 | } | 471 | } |
468 | ext[localExtIndex++] = curr; | 472 | ext[localExtIndex++] = curr; |
469 | } | 473 | } |
470 | maxFilenameLen = 250 - localExtIndex; | 474 | maxFilenameLen = newLen - CRC_LEN - localExtIndex; |
471 | if (newIndex > maxFilenameLen) | 475 | if (newIndex > maxFilenameLen) |
472 | newIndex = maxFilenameLen; | 476 | newIndex = maxFilenameLen; |
473 | else | 477 | else |
474 | newIndex = newExtIndex; | 478 | newIndex = newExtIndex; |
475 | } else if (newIndex > 250) | 479 | } else if (newIndex > newLen - CRC_LEN) |
476 | newIndex = 250; | 480 | newIndex = newLen - CRC_LEN; |
477 | newName[newIndex++] = CRC_MARK; | 481 | newName[newIndex++] = CRC_MARK; |
478 | valueCRC = crc_itu_t(0, fidName, fidNameLen); | 482 | valueCRC = crc_itu_t(0, fidName, fidNameLen); |
479 | newName[newIndex++] = hex_asc_upper_hi(valueCRC >> 8); | 483 | newName[newIndex++] = hex_asc_upper_hi(valueCRC >> 8); |