aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
authorAndrew Gabbasov <andrew_gabbasov@mentor.com>2016-04-25 07:19:38 -0400
committerJan Kara <jack@suse.cz>2016-04-25 09:18:50 -0400
commitc26f6c61578852f679787d555e6d07804e1f5f14 (patch)
tree2fd38eb6ed58ef4495a93fcae0bc1a4c75a035c1 /fs/udf
parent95d0c4277c27520cabdc40646f5a2e507fcd315a (diff)
udf: Fix conversion of 'dstring' fields to UTF8
Commit 9293fcfbc1812a22ad5ce1b542eb90c1bbe01be1 ("udf: Remove struct ustr as non-needed intermediate storage"), while getting rid of 'struct ustr', does not take any special care of 'dstring' fields and effectively use fixed field length instead of actual string length, encoded in the last byte of the field. Also, commit 484a10f49387e4386bf2708532e75bf78ffea2cb ("udf: Merge linux specific translation into CS0 conversion function") introduced checking of the length of the string being converted, requiring proper alignment to number of bytes constituing each character. The UDF volume identifier is represented as a 32-bytes 'dstring', and needs to be converted from CS0 to UTF8, while mounting UDF filesystem. The changes in mentioned commits can in some cases lead to incorrect handling of volume identifier: - if the actual string in 'dstring' is of maximal length and does not have zero bytes separating it from dstring encoded length in last byte, that last byte may be included in conversion, thus making incorrect resulting string; - if the identifier is encoded with 2-bytes characters (compression code is 16), the length of 31 bytes (32 bytes of field length minus 1 byte of compression code), taken as the string length, is reported as an incorrect (unaligned) length, and the conversion fails, which in its turn leads to volume mounting failure. This patch introduces handling of 'dstring' encoded length field in udf_CS0toUTF8 function, that is used in all and only cases when 'dstring' fields are converted. Currently these cases are processing of Volume Identifier and Volume Set Identifier fields. The function is also renamed to udf_dstrCS0toUTF8 to distinctly indicate that it handles 'dstring' input. Signed-off-by: Andrew Gabbasov <andrew_gabbasov@mentor.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/super.c4
-rw-r--r--fs/udf/udfdecl.h2
-rw-r--r--fs/udf/unicode.c16
3 files changed, 17 insertions, 5 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index fa92fe839fda..36661acaf33b 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -919,14 +919,14 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
919#endif 919#endif
920 } 920 }
921 921
922 ret = udf_CS0toUTF8(outstr, 31, pvoldesc->volIdent, 32); 922 ret = udf_dstrCS0toUTF8(outstr, 31, pvoldesc->volIdent, 32);
923 if (ret < 0) 923 if (ret < 0)
924 goto out_bh; 924 goto out_bh;
925 925
926 strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret); 926 strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
927 udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident); 927 udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident);
928 928
929 ret = udf_CS0toUTF8(outstr, 127, pvoldesc->volSetIdent, 128); 929 ret = udf_dstrCS0toUTF8(outstr, 127, pvoldesc->volSetIdent, 128);
930 if (ret < 0) 930 if (ret < 0)
931 goto out_bh; 931 goto out_bh;
932 932
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 972b70625614..263829ef1873 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -212,7 +212,7 @@ extern int udf_get_filename(struct super_block *, const uint8_t *, int,
212 uint8_t *, int); 212 uint8_t *, int);
213extern int udf_put_filename(struct super_block *, const uint8_t *, int, 213extern int udf_put_filename(struct super_block *, const uint8_t *, int,
214 uint8_t *, int); 214 uint8_t *, int);
215extern int udf_CS0toUTF8(uint8_t *, int, const uint8_t *, int); 215extern int udf_dstrCS0toUTF8(uint8_t *, int, const uint8_t *, int);
216 216
217/* ialloc.c */ 217/* ialloc.c */
218extern void udf_free_inode(struct inode *); 218extern void udf_free_inode(struct inode *);
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
index 3ff42f4437f3..695389a4fc23 100644
--- a/fs/udf/unicode.c
+++ b/fs/udf/unicode.c
@@ -335,9 +335,21 @@ try_again:
335 return u_len; 335 return u_len;
336} 336}
337 337
338int udf_CS0toUTF8(uint8_t *utf_o, int o_len, const uint8_t *ocu_i, int i_len) 338int udf_dstrCS0toUTF8(uint8_t *utf_o, int o_len,
339 const uint8_t *ocu_i, int i_len)
339{ 340{
340 return udf_name_from_CS0(utf_o, o_len, ocu_i, i_len, 341 int s_len = 0;
342
343 if (i_len > 0) {
344 s_len = ocu_i[i_len - 1];
345 if (s_len >= i_len) {
346 pr_err("incorrect dstring lengths (%d/%d)\n",
347 s_len, i_len);
348 return -EINVAL;
349 }
350 }
351
352 return udf_name_from_CS0(utf_o, o_len, ocu_i, s_len,
341 udf_uni2char_utf8, 0); 353 udf_uni2char_utf8, 0);
342} 354}
343 355