aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/udf/dir.c3
-rw-r--r--fs/udf/namei.c3
-rw-r--r--fs/udf/symlink.c31
-rw-r--r--fs/udf/udfdecl.h3
-rw-r--r--fs/udf/unicode.c28
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
33static void udf_pc_to_char(struct super_block *sb, unsigned char *from, 33static 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
78static int udf_symlink_filler(struct file *file, struct page *page) 97static 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 */
214extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); 214extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *,
215 int);
215extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, 216extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *,
216 int); 217 int);
217extern int udf_build_ustr(struct ustr *, dstring *, int); 218extern 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
31static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); 31static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *,
32 int);
32 33
33static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) 34static 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
336int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, 337int 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);
371out2: 373out2:
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
407static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, 411static 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);