summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2018-11-16 07:43:17 -0500
committerJan Kara <jack@suse.cz>2018-11-19 04:27:59 -0500
commitb54e41f5efcb4316b2f30b30c2535cc194270373 (patch)
treea4a402739d91359efeb7e8f5c0c5eeeb4ba93301
parent9ff01193a20d391e8dbce4403dd5ef87c7eaaca6 (diff)
udf: Allow mounting volumes with incorrect identification strings
Commit c26f6c615788 ("udf: Fix conversion of 'dstring' fields to UTF8") started to be more strict when checking whether converted strings are properly formatted. Sudip reports that there are DVDs where the volume identification string is actually too long - UDF reports: [ 632.309320] UDF-fs: incorrect dstring lengths (32/32) during mount and fails the mount. This is mostly harmless failure as we don't need volume identification (and even less volume set identification) for anything. So just truncate the volume identification string if it is too long and replace it with 'Invalid' if we just cannot convert it for other reasons. This keeps slightly incorrect media still mountable. CC: stable@vger.kernel.org Fixes: c26f6c615788 ("udf: Fix conversion of 'dstring' fields to UTF8") Reported-and-tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--fs/udf/super.c16
-rw-r--r--fs/udf/unicode.c14
2 files changed, 21 insertions, 9 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 8f2f56d9a1bb..e3d684ea3203 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -827,16 +827,20 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
827 827
828 828
829 ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32); 829 ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32);
830 if (ret < 0) 830 if (ret < 0) {
831 goto out_bh; 831 strcpy(UDF_SB(sb)->s_volume_ident, "InvalidName");
832 832 pr_warn("incorrect volume identification, setting to "
833 strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret); 833 "'InvalidName'\n");
834 } else {
835 strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
836 }
834 udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident); 837 udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident);
835 838
836 ret = udf_dstrCS0toChar(sb, outstr, 127, pvoldesc->volSetIdent, 128); 839 ret = udf_dstrCS0toChar(sb, outstr, 127, pvoldesc->volSetIdent, 128);
837 if (ret < 0) 840 if (ret < 0) {
841 ret = 0;
838 goto out_bh; 842 goto out_bh;
839 843 }
840 outstr[ret] = 0; 844 outstr[ret] = 0;
841 udf_debug("volSetIdent[] = '%s'\n", outstr); 845 udf_debug("volSetIdent[] = '%s'\n", outstr);
842 846
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
index 45234791fec2..5fcfa96463eb 100644
--- a/fs/udf/unicode.c
+++ b/fs/udf/unicode.c
@@ -351,6 +351,11 @@ try_again:
351 return u_len; 351 return u_len;
352} 352}
353 353
354/*
355 * Convert CS0 dstring to output charset. Warning: This function may truncate
356 * input string if it is too long as it is used for informational strings only
357 * and it is better to truncate the string than to refuse mounting a media.
358 */
354int udf_dstrCS0toChar(struct super_block *sb, uint8_t *utf_o, int o_len, 359int udf_dstrCS0toChar(struct super_block *sb, uint8_t *utf_o, int o_len,
355 const uint8_t *ocu_i, int i_len) 360 const uint8_t *ocu_i, int i_len)
356{ 361{
@@ -359,9 +364,12 @@ int udf_dstrCS0toChar(struct super_block *sb, uint8_t *utf_o, int o_len,
359 if (i_len > 0) { 364 if (i_len > 0) {
360 s_len = ocu_i[i_len - 1]; 365 s_len = ocu_i[i_len - 1];
361 if (s_len >= i_len) { 366 if (s_len >= i_len) {
362 pr_err("incorrect dstring lengths (%d/%d)\n", 367 pr_warn("incorrect dstring lengths (%d/%d),"
363 s_len, i_len); 368 " truncating\n", s_len, i_len);
364 return -EINVAL; 369 s_len = i_len - 1;
370 /* 2-byte encoding? Need to round properly... */
371 if (ocu_i[0] == 16)
372 s_len -= (s_len - 1) & 2;
365 } 373 }
366 } 374 }
367 375