+++ /dev/null
-From e237ec37ec154564f8690c5bd1795339955eeef9 Mon Sep 17 00:00:00 2001
-From: Jan Kara <jack@suse.cz>
-Date: Fri, 19 Dec 2014 14:27:55 +0100
-Subject: udf: Check component length before reading it
-
-From: Jan Kara <jack@suse.cz>
-
-commit e237ec37ec154564f8690c5bd1795339955eeef9 upstream.
-
-Check that length specified in a component of a symlink fits in the
-input buffer we are reading. Also properly ignore component length for
-component types that do not use it. Otherwise we read memory after end
-of buffer for corrupted udf image.
-
-Reported-by: Carl Henrik Lunde <chlunde@ping.uio.no>
-Signed-off-by: Jan Kara <jack@suse.cz>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- fs/udf/symlink.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
---- a/fs/udf/symlink.c
-+++ b/fs/udf/symlink.c
-@@ -42,14 +42,17 @@ static int udf_pc_to_char(struct super_b
- tolen--;
- while (elen < fromlen) {
- pc = (struct pathComponent *)(from + elen);
-+ elen += sizeof(struct pathComponent);
- switch (pc->componentType) {
- case 1:
- /*
- * Symlink points to some place which should be agreed
- * upon between originator and receiver of the media. Ignore.
- */
-- if (pc->lengthComponentIdent > 0)
-+ if (pc->lengthComponentIdent > 0) {
-+ elen += pc->lengthComponentIdent;
- break;
-+ }
- /* Fall through */
- case 2:
- if (tolen == 0)
-@@ -74,6 +77,9 @@ static int udf_pc_to_char(struct super_b
- /* that would be . - just ignore */
- break;
- case 5:
-+ elen += pc->lengthComponentIdent;
-+ if (elen > fromlen)
-+ return -EIO;
- comp_len = udf_get_filename(sb, pc->componentIdent,
- pc->lengthComponentIdent,
- p, tolen);
-@@ -85,7 +91,6 @@ static int udf_pc_to_char(struct super_b
- tolen--;
- break;
- }
-- elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
- }
- if (p > to + 1)
- p[-1] = '\0';
+++ /dev/null
-From 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 Mon Sep 17 00:00:00 2001
-From: Jan Kara <jack@suse.cz>
-Date: Thu, 18 Dec 2014 22:37:50 +0100
-Subject: udf: Check path length when reading symlink
-
-From: Jan Kara <jack@suse.cz>
-
-commit 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 upstream.
-
-Symlink reading code does not check whether the resulting path fits into
-the page provided by the generic code. This isn't as easy as just
-checking the symlink size because of various encoding conversions we
-perform on path. So we have to check whether there is still enough space
-in the buffer on the fly.
-
-Reported-by: Carl Henrik Lunde <chlunde@ping.uio.no>
-Signed-off-by: Jan Kara <jack@suse.cz>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- fs/udf/dir.c | 3 ++-
- fs/udf/namei.c | 3 ++-
- fs/udf/symlink.c | 31 ++++++++++++++++++++++++++-----
- fs/udf/udfdecl.h | 3 ++-
- fs/udf/unicode.c | 28 ++++++++++++++++------------
- 5 files changed, 48 insertions(+), 20 deletions(-)
-
---- a/fs/udf/dir.c
-+++ b/fs/udf/dir.c
-@@ -167,7 +167,8 @@ static int udf_readdir(struct file *file
- continue;
- }
-
-- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
-+ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname,
-+ UDF_NAME_LEN);
- if (!flen)
- continue;
-
---- a/fs/udf/namei.c
-+++ b/fs/udf/namei.c
-@@ -233,7 +233,8 @@ static struct fileIdentDesc *udf_find_en
- if (!lfi)
- continue;
-
-- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
-+ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname,
-+ UDF_NAME_LEN);
- if (flen && udf_match(flen, fname, child->len, child->name))
- goto out_ok;
- }
---- a/fs/udf/symlink.c
-+++ b/fs/udf/symlink.c
-@@ -30,13 +30,16 @@
- #include <linux/buffer_head.h>
- #include "udf_i.h"
-
--static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
-- int fromlen, unsigned char *to)
-+static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
-+ int fromlen, unsigned char *to, int tolen)
- {
- struct pathComponent *pc;
- int elen = 0;
-+ int comp_len;
- unsigned char *p = to;
-
-+ /* Reserve one byte for terminating \0 */
-+ tolen--;
- while (elen < fromlen) {
- pc = (struct pathComponent *)(from + elen);
- switch (pc->componentType) {
-@@ -49,22 +52,37 @@ static void udf_pc_to_char(struct super_
- break;
- /* Fall through */
- case 2:
-+ if (tolen == 0)
-+ return -ENAMETOOLONG;
- p = to;
- *p++ = '/';
-+ tolen--;
- break;
- case 3:
-+ if (tolen < 3)
-+ return -ENAMETOOLONG;
- memcpy(p, "../", 3);
- p += 3;
-+ tolen -= 3;
- break;
- case 4:
-+ if (tolen < 2)
-+ return -ENAMETOOLONG;
- memcpy(p, "./", 2);
- p += 2;
-+ tolen -= 2;
- /* that would be . - just ignore */
- break;
- case 5:
-- p += udf_get_filename(sb, pc->componentIdent, p,
-- pc->lengthComponentIdent);
-+ comp_len = udf_get_filename(sb, pc->componentIdent,
-+ pc->lengthComponentIdent,
-+ p, tolen);
-+ p += comp_len;
-+ tolen -= comp_len;
-+ if (tolen == 0)
-+ return -ENAMETOOLONG;
- *p++ = '/';
-+ tolen--;
- break;
- }
- elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
-@@ -73,6 +91,7 @@ static void udf_pc_to_char(struct super_
- p[-1] = '\0';
- else
- p[0] = '\0';
-+ return 0;
- }
-
- static int udf_symlink_filler(struct file *file, struct page *page)
-@@ -100,8 +119,10 @@ static int udf_symlink_filler(struct fil
- symlink = bh->b_data;
- }
-
-- udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
-+ err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE);
- brelse(bh);
-+ if (err)
-+ goto out_unlock_inode;
-
- up_read(&iinfo->i_data_sem);
- SetPageUptodate(page);
---- a/fs/udf/udfdecl.h
-+++ b/fs/udf/udfdecl.h
-@@ -201,7 +201,8 @@ udf_get_lb_pblock(struct super_block *sb
- }
-
- /* unicode.c */
--extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
-+extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *,
-+ int);
- extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *,
- int);
- extern int udf_build_ustr(struct ustr *, dstring *, int);
---- a/fs/udf/unicode.c
-+++ b/fs/udf/unicode.c
-@@ -28,7 +28,8 @@
-
- #include "udf_sb.h"
-
--static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
-+static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *,
-+ int);
-
- static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
- {
-@@ -333,8 +334,8 @@ try_again:
- return u_len + 1;
- }
-
--int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname,
-- int flen)
-+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;
-@@ -347,7 +348,7 @@ int udf_get_filename(struct super_block
- if (!unifilename)
- goto out1;
-
-- if (udf_build_ustr_exact(unifilename, sname, flen))
-+ if (udf_build_ustr_exact(unifilename, sname, slen))
- goto out2;
-
- if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) {
-@@ -366,7 +367,8 @@ int udf_get_filename(struct super_block
- } else
- goto out2;
-
-- len = udf_translate_to_linux(dname, filename->u_name, filename->u_len,
-+ len = udf_translate_to_linux(dname, dlen,
-+ filename->u_name, filename->u_len,
- unifilename->u_name, unifilename->u_len);
- out2:
- kfree(unifilename);
-@@ -403,10 +405,12 @@ int udf_put_filename(struct super_block
- #define EXT_MARK '.'
- #define CRC_MARK '#'
- #define EXT_SIZE 5
-+/* Number of chars we need to store generated CRC to make filename unique */
-+#define CRC_LEN 5
-
--static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
-- int udfLen, uint8_t *fidName,
-- int fidNameLen)
-+static int udf_translate_to_linux(uint8_t *newName, int newLen,
-+ uint8_t *udfName, int udfLen,
-+ uint8_t *fidName, int fidNameLen)
- {
- int index, newIndex = 0, needsCRC = 0;
- int extIndex = 0, newExtIndex = 0, hasExt = 0;
-@@ -440,7 +444,7 @@ static int udf_translate_to_linux(uint8_
- newExtIndex = newIndex;
- }
- }
-- if (newIndex < 256)
-+ if (newIndex < newLen)
- newName[newIndex++] = curr;
- else
- needsCRC = 1;
-@@ -468,13 +472,13 @@ static int udf_translate_to_linux(uint8_
- }
- ext[localExtIndex++] = curr;
- }
-- maxFilenameLen = 250 - localExtIndex;
-+ maxFilenameLen = newLen - CRC_LEN - localExtIndex;
- if (newIndex > maxFilenameLen)
- newIndex = maxFilenameLen;
- else
- newIndex = newExtIndex;
-- } else if (newIndex > 250)
-- newIndex = 250;
-+ } else if (newIndex > newLen - CRC_LEN)
-+ newIndex = newLen - CRC_LEN;
- newName[newIndex++] = CRC_MARK;
- valueCRC = crc_itu_t(0, fidName, fidNameLen);
- newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];