From 5ceb8b554dcaaf6844415cd2616ce2e0132530fa Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 8 Apr 2015 21:23:51 +0200 Subject: udf: Return -ENOMEM when allocation fails in udf_get_filename() Return -ENOMEM when allocation fails in udf_get_filename(). Update udf_pc_to_char(), udf_readdir(), and udf_find_entry() to handle the error appropriately. This allows us to pass appropriate error to userspace instead of corrupting symlink contents by omitting some path elements. Signed-off-by: Fabian Frederick Signed-off-by: Jan Kara --- fs/udf/unicode.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'fs/udf/unicode.c') diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index b84fee372734..4911c1d84882 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -338,15 +338,17 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, uint8_t *dname, int dlen) { struct ustr *filename, *unifilename; - int len = 0; + int ret = 0; filename = kmalloc(sizeof(struct ustr), GFP_NOFS); if (!filename) - return 0; + return -ENOMEM; unifilename = kmalloc(sizeof(struct ustr), GFP_NOFS); - if (!unifilename) + if (!unifilename) { + ret = -ENOMEM; goto out1; + } if (udf_build_ustr_exact(unifilename, sname, slen)) goto out2; @@ -367,14 +369,14 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, } else goto out2; - len = udf_translate_to_linux(dname, dlen, + ret = udf_translate_to_linux(dname, dlen, filename->u_name, filename->u_len, unifilename->u_name, unifilename->u_len); out2: kfree(unifilename); out1: kfree(filename); - return len; + return ret; } int udf_put_filename(struct super_block *sb, const uint8_t *sname, -- cgit v1.2.3 From 31f2566f33a6a25ac0baf402316e37e76632445f Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 8 Apr 2015 21:23:52 +0200 Subject: udf: remove unnecessary test in udf_build_ustr_exact() We can remove parameter checks: udf_build_ustr_exact() is only called by udf_get_filename() which now assures dest is not NULL udf_find_entry() and udf_readdir() call udf_get_filename() after checking sname udf_symlink_filler() calls udf_pc_to_char() with sname=kmap(page). udf_find_entry() and udf_readdir() call udf_get_filename with UDF_NAME_LEN udf_pc_to_char() with PAGE_SIZE Suggested-by: Jan Kara Signed-off-by: Fabian Frederick Signed-off-by: Jan Kara --- fs/udf/unicode.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'fs/udf/unicode.c') diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 4911c1d84882..e2c079aae7c0 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -68,17 +68,12 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size) /* * udf_build_ustr_exact */ -static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize) +static void udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize) { - if ((!dest) || (!ptr) || (!exactsize)) - return -1; - memset(dest, 0, sizeof(struct ustr)); dest->u_cmpID = ptr[0]; dest->u_len = exactsize - 1; memcpy(dest->u_name, ptr + 1, exactsize - 1); - - return 0; } /* @@ -340,6 +335,9 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, struct ustr *filename, *unifilename; int ret = 0; + if (!slen) + return -EIO; + filename = kmalloc(sizeof(struct ustr), GFP_NOFS); if (!filename) return -ENOMEM; @@ -350,9 +348,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, goto out1; } - if (udf_build_ustr_exact(unifilename, sname, slen)) - goto out2; - + udf_build_ustr_exact(unifilename, sname, slen); if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { if (!udf_CS0toUTF8(filename, unifilename)) { udf_debug("Failed in udf_get_filename: sname = %s\n", -- cgit v1.2.3 From d67e4a481425106a43c8d3cef82a82cc31b4edd8 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 8 Apr 2015 21:23:53 +0200 Subject: udf: unicode: update function name in comments Signed-off-by: Fabian Frederick Signed-off-by: Jan Kara --- fs/udf/unicode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/udf/unicode.c') diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index e2c079aae7c0..41c3bef1d226 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -77,7 +77,7 @@ static void udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize) } /* - * udf_ocu_to_utf8 + * udf_CS0toUTF8 * * PURPOSE * Convert OSTA Compressed Unicode to the UTF-8 equivalent. @@ -149,7 +149,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i) /* * - * udf_utf8_to_ocu + * udf_UTF8toCS0 * * PURPOSE * Convert UTF-8 to the OSTA Compressed Unicode equivalent. -- cgit v1.2.3 From e9d4cf411f7582537ed0038d0f32a8743b75e58a Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 8 Apr 2015 21:23:54 +0200 Subject: udf: improve error management in udf_CS0toUTF8() udf_CS0toUTF8() now returns -EINVAL on error. udf_load_pvoldesc() and udf_get_filename() do the same. Suggested-by: Jan Kara Signed-off-by: Fabian Frederick Signed-off-by: Jan Kara --- fs/udf/unicode.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'fs/udf/unicode.c') diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 41c3bef1d226..35cc9477b066 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -89,7 +89,7 @@ static void udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize) * both of type "struct ustr *" * * POST-CONDITIONS - * Zero on success. + * >= 0 on success. * * HISTORY * November 12, 1997 - Andrew E. Mileski @@ -112,7 +112,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i) memset(utf_o, 0, sizeof(struct ustr)); pr_err("unknown compression code (%d) stri=%s\n", cmp_id, ocu_i->u_name); - return 0; + return -EINVAL; } ocu = ocu_i->u_name; @@ -350,7 +350,8 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, udf_build_ustr_exact(unifilename, sname, slen); if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { - if (!udf_CS0toUTF8(filename, unifilename)) { + ret = udf_CS0toUTF8(filename, unifilename); + if (ret < 0) { udf_debug("Failed in udf_get_filename: sname = %s\n", sname); goto out2; -- cgit v1.2.3 From 78fc2e694f35d1d027448e5b7641f32719073320 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 8 Apr 2015 21:23:55 +0200 Subject: udf: improve error management in udf_CS0toNLS() Only callsite udf_get_filename() now returns error code as well. Suggested-by: Jan Kara Signed-off-by: Fabian Frederick Signed-off-by: Jan Kara --- fs/udf/unicode.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'fs/udf/unicode.c') diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 35cc9477b066..658aa14cc474 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -265,7 +265,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, memset(utf_o, 0, sizeof(struct ustr)); pr_err("unknown compression code (%d) stri=%s\n", cmp_id, ocu_i->u_name); - return 0; + return -EINVAL; } ocu = ocu_i->u_name; @@ -357,8 +357,9 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, goto out2; } } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { - if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename, - unifilename)) { + ret = udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename, + unifilename); + if (ret < 0) { udf_debug("Failed in udf_get_filename: sname = %s\n", sname); goto out2; -- cgit v1.2.3 From 5dce54b71e6185dae07ad12ca17ce30aa64022cd Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 8 Apr 2015 21:23:56 +0200 Subject: udf: bug on exotic flag in udf_get_filename() UDF volume is only mounted with UDF_FLAG_UTF8 or UDF_FLAG_NLS_MAP (see fill udf_fill_super(). BUG() if we have something different in udf_get_filename() Suggested-by: Jan Kara Signed-off-by: Fabian Frederick Signed-off-by: Jan Kara --- fs/udf/unicode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/udf/unicode.c') diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 658aa14cc474..97b23b0f9713 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -365,7 +365,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, goto out2; } } else - goto out2; + BUG(); ret = udf_translate_to_linux(dname, dlen, filename->u_name, filename->u_len, -- cgit v1.2.3 From 6ce638367382ea8015cf64619e9bca4e207ef36f Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 8 Apr 2015 21:23:57 +0200 Subject: udf: Make udf_get_filename() return error instead of 0 length file name Zero length file name isn't really valid. So check the length of the final file name generated by udf_translate_to_linux() and return -EINVAL instead of zero length file name. Update caller of udf_get_filename() to not check for 0 return value. Signed-off-by: Fabian Frederick Signed-off-by: Jan Kara --- fs/udf/unicode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fs/udf/unicode.c') diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 97b23b0f9713..ab478e62baae 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -333,7 +333,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, uint8_t *dname, int dlen) { struct ustr *filename, *unifilename; - int ret = 0; + int ret; if (!slen) return -EIO; @@ -370,6 +370,9 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, ret = udf_translate_to_linux(dname, dlen, filename->u_name, filename->u_len, unifilename->u_name, unifilename->u_len); + /* Zero length filename isn't valid... */ + if (ret == 0) + ret = -EINVAL; out2: kfree(unifilename); out1: -- cgit v1.2.3