[kernel] r22739 - in dists/squeeze-security/linux-2.6/debian: . patches/bugfix/all patches/series
Ben Hutchings
benh at moszumanska.debian.org
Sun Jun 14 17:27:26 UTC 2015
Author: benh
Date: Sun Jun 14 17:27:25 2015
New Revision: 22739
Log:
Add udf security fixes
Added:
dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-check-component-length-before-reading-it.patch
dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-check-path-length-when-reading-symlink.patch
dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-treat-symlink-component-of-type-2-as.patch
dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-verify-i_size-when-loading-inode.patch
dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-verify-symlink-size-before-loading-it.patch
Modified:
dists/squeeze-security/linux-2.6/debian/changelog
dists/squeeze-security/linux-2.6/debian/patches/series/48squeeze12
Modified: dists/squeeze-security/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/changelog Thu Jun 11 21:47:07 2015 (r22738)
+++ dists/squeeze-security/linux-2.6/debian/changelog Sun Jun 14 17:27:25 2015 (r22739)
@@ -46,6 +46,12 @@
* eCryptfs: Remove buggy and unnecessary write in file name decode routine
(CVE-2014-9683)
* HID: fix a couple of off-by-ones (CVE-2014-3184)
+ * udf: Verify i_size when loading inode (CVE-2014-9728, CVE-2014-9729)
+ * udf: Verify symlink size before loading it (CVE-2014-9728)
+ * udf: Treat symlink component of type 2 as /
+ * udf: Check path length when reading symlink (CVE-2014-9731)
+ * udf: Check component length before reading it
+ (CVE-2014-9728, CVE-2014-9730)
-- Ben Hutchings <ben at decadent.org.uk> Sun, 12 Apr 2015 17:12:31 +0100
Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-check-component-length-before-reading-it.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-check-component-length-before-reading-it.patch Sun Jun 14 17:27:25 2015 (r22739)
@@ -0,0 +1,58 @@
+From: Jan Kara <jack at suse.cz>
+Date: Fri, 19 Dec 2014 14:27:55 +0100
+Subject: [4/4] udf: Check component length before reading it
+Origin: https://git.kernel.org/linus/e237ec37ec154564f8690c5bd1795339955eeef9
+
+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 at ping.uio.no>
+CC: stable at vger.kernel.org
+Signed-off-by: Jan Kara <jack at suse.cz>
+---
+ fs/udf/symlink.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
+index 0f1b3a2..ac10ca9 100644
+--- a/fs/udf/symlink.c
++++ b/fs/udf/symlink.c
+@@ -44,14 +44,17 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
+ 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)
+@@ -76,6 +79,9 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
+ /* 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);
+@@ -87,7 +93,6 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
+ tolen--;
+ break;
+ }
+- elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
+ }
+ if (p > to + 1)
+ p[-1] = '\0';
Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-check-path-length-when-reading-symlink.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-check-path-length-when-reading-symlink.patch Sun Jun 14 17:27:25 2015 (r22739)
@@ -0,0 +1,234 @@
+From: Jan Kara <jack at suse.cz>
+Date: Thu, 18 Dec 2014 22:37:50 +0100
+Subject: [3/4] udf: Check path length when reading symlink
+Origin: https://git.kernel.org/linus/0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14
+
+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.
+
+CC: stable at vger.kernel.org
+Reported-by: Carl Henrik Lunde <chlunde at ping.uio.no>
+Signed-off-by: Jan Kara <jack at suse.cz>
+[bwh: Backported to 2.6.32: adjust context, indentation]
+---
+ 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(-)
+
+diff --git a/fs/udf/dir.c b/fs/udf/dir.c
+index a012c51..a7690b4 100644
+--- a/fs/udf/dir.c
++++ b/fs/udf/dir.c
+@@ -164,7 +164,8 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
+ struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation);
+
+ iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0);
+- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
++ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname,
++ UDF_NAME_LEN);
+ dt_type = DT_UNKNOWN;
+ }
+
+diff --git a/fs/udf/namei.c b/fs/udf/namei.c
+index c12e260..6ff19b5 100644
+--- a/fs/udf/namei.c
++++ b/fs/udf/namei.c
+@@ -237,7 +237,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+ 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;
+ }
+diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
+index c3aa6fa..0f1b3a2 100644
+--- a/fs/udf/symlink.c
++++ b/fs/udf/symlink.c
+@@ -32,13 +32,16 @@
+ #include <linux/buffer_head.h>
+ #include "udf_i.h"
+
+-static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen,
+- char *to)
++static int udf_pc_to_char(struct super_block *sb, char *from,
++ int fromlen, char *to, int tolen)
+ {
+ struct pathComponent *pc;
+ int elen = 0;
++ int comp_len;
+ char *p = to;
+
++ /* Reserve one byte for terminating \0 */
++ tolen--;
+ while (elen < fromlen) {
+ pc = (struct pathComponent *)(from + elen);
+ switch (pc->componentType) {
+@@ -51,22 +54,37 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
+ 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;
+@@ -75,6 +93,7 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
+ p[-1] = '\0';
+ else
+ p[0] = '\0';
++ return 0;
+ }
+
+ static int udf_symlink_filler(struct file *file, struct page *page)
+@@ -107,8 +126,10 @@ static int udf_symlink_filler(struct file *file, struct page *page)
+ 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;
+
+ unlock_kernel();
+ SetPageUptodate(page);
+diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
+index 1cc3c99..47bb3f5 100644
+--- a/fs/udf/udfdecl.h
++++ b/fs/udf/udfdecl.h
+@@ -200,7 +200,8 @@ udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc,
+ }
+
+ /* 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);
+diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
+index afd470e..b84fee3 100644
+--- a/fs/udf/unicode.c
++++ b/fs/udf/unicode.c
+@@ -27,7 +27,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)
+ {
+@@ -332,8 +333,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;
+@@ -346,7 +347,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname,
+ 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)) {
+@@ -365,7 +366,8 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname,
+ } 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);
+@@ -402,10 +404,12 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname,
+ #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;
+@@ -439,7 +443,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
+ newExtIndex = newIndex;
+ }
+ }
+- if (newIndex < 256)
++ if (newIndex < newLen)
+ newName[newIndex++] = curr;
+ else
+ needsCRC = 1;
+@@ -467,13 +471,13 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
+ }
+ 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];
Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-treat-symlink-component-of-type-2-as.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-treat-symlink-component-of-type-2-as.patch Sun Jun 14 17:27:25 2015 (r22739)
@@ -0,0 +1,42 @@
+From: Jan Kara <jack at suse.cz>
+Date: Mon, 12 Dec 2011 15:13:50 +0100
+Subject: udf: Treat symlink component of type 2 as /
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://git.kernel.org/linus/fef2e9f3301934773e4f1b3cc5c7bffb119346b8
+
+Currently, we ignore symlink component of type 2. But mkisofs and other OS'
+seem to treat it as / so do the same for compatibility.
+
+Reported-by: "Gábor S." <otnaccess at hotmail.com>
+Signed-off-by: Jan Kara <jack at suse.cz>
+---
+ fs/udf/symlink.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
+index b1d4488..d7c6dbe 100644
+--- a/fs/udf/symlink.c
++++ b/fs/udf/symlink.c
+@@ -43,10 +43,16 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
+ pc = (struct pathComponent *)(from + elen);
+ switch (pc->componentType) {
+ case 1:
+- if (pc->lengthComponentIdent == 0) {
+- p = to;
+- *p++ = '/';
+- }
++ /*
++ * Symlink points to some place which should be agreed
++ * upon between originator and receiver of the media. Ignore.
++ */
++ if (pc->lengthComponentIdent > 0)
++ break;
++ /* Fall through */
++ case 2:
++ p = to;
++ *p++ = '/';
+ break;
+ case 3:
+ memcpy(p, "../", 3);
Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-verify-i_size-when-loading-inode.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-verify-i_size-when-loading-inode.patch Sun Jun 14 17:27:25 2015 (r22739)
@@ -0,0 +1,45 @@
+From: Jan Kara <jack at suse.cz>
+Date: Fri, 19 Dec 2014 12:03:53 +0100
+Subject: [1/4] udf: Verify i_size when loading inode
+Origin: https://git.kernel.org/linus/e159332b9af4b04d882dbcfe1bb0117f0a6d4b58
+
+Verify that inode size is sane when loading inode with data stored in
+ICB. Otherwise we may get confused later when working with the inode and
+inode size is too big.
+
+CC: stable at vger.kernel.org
+Reported-by: Carl Henrik Lunde <chlunde at ping.uio.no>
+Signed-off-by: Jan Kara <jack at suse.cz>
+[bwh: Backported to 3.2: on error, call make_bad_inode() then return]
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ fs/udf/inode.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -1286,6 +1286,24 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ iinfo->i_lenEAttr;
+ }
+
++ /* Sanity checks for files in ICB so that we don't get confused later */
++ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
++ /*
++ * For file in ICB data is stored in allocation descriptor
++ * so sizes should match
++ */
++ if (iinfo->i_lenAlloc != inode->i_size) {
++ make_bad_inode(inode);
++ return;
++ }
++ /* File in ICB has to fit in there... */
++ if (inode->i_size > inode->i_sb->s_blocksize -
++ udf_file_entry_alloc_offset(inode)) {
++ make_bad_inode(inode);
++ return;
++ }
++ }
++
+ switch (fe->icbTag.fileType) {
+ case ICBTAG_FILE_TYPE_DIRECTORY:
+ inode->i_op = &udf_dir_inode_operations;
Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-verify-symlink-size-before-loading-it.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/udf-verify-symlink-size-before-loading-it.patch Sun Jun 14 17:27:25 2015 (r22739)
@@ -0,0 +1,64 @@
+From: Jan Kara <jack at suse.cz>
+Date: Fri, 19 Dec 2014 12:21:47 +0100
+Subject: [2/4] udf: Verify symlink size before loading it
+Origin: https://git.kernel.org/linus/a1d47b262952a45aae62bd49cfaf33dd76c11a2c
+
+UDF specification allows arbitrarily large symlinks. However we support
+only symlinks at most one block large. Check the length of the symlink
+so that we don't access memory beyond end of the symlink block.
+
+CC: stable at vger.kernel.org
+Reported-by: Carl Henrik Lunde <chlunde at gmail.com>
+Signed-off-by: Jan Kara <jack at suse.cz>
+bwh: Backported to 2.6.32: adjust context]
+---
+ fs/udf/symlink.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
+index 6fb7945..c3aa6fa 100644
+--- a/fs/udf/symlink.c
++++ b/fs/udf/symlink.c
+@@ -76,10 +76,16 @@ static int udf_symlink_filler(struct file *file, struct page *page)
+ struct inode *inode = page->mapping->host;
+ struct buffer_head *bh = NULL;
+ char *symlink;
+- int err = -EIO;
++ int err;
+ char *p = kmap(page);
+ struct udf_inode_info *iinfo;
+
++ /* We don't support symlinks longer than one block */
++ if (inode->i_size > inode->i_sb->s_blocksize) {
++ err = -ENAMETOOLONG;
++ goto out_unmap;
++ }
++
+ lock_kernel();
+ iinfo = UDF_I(inode);
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
+@@ -87,8 +93,10 @@ static int udf_symlink_filler(struct file *file, struct page *page)
+ } else {
+ bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
+
+- if (!bh)
+- goto out;
++ if (!bh) {
++ err = -EIO;
++ goto out_unlock_inode;
++ }
+
+ symlink = bh->b_data;
+ }
+@@ -102,9 +110,10 @@ static int udf_symlink_filler(struct file *file, struct page *page)
+ unlock_page(page);
+ return 0;
+
+-out:
++out_unlock_inode:
+ unlock_kernel();
+ SetPageError(page);
++out_unmap:
+ kunmap(page);
+ unlock_page(page);
+ return err;
Modified: dists/squeeze-security/linux-2.6/debian/patches/series/48squeeze12
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/patches/series/48squeeze12 Thu Jun 11 21:47:07 2015 (r22738)
+++ dists/squeeze-security/linux-2.6/debian/patches/series/48squeeze12 Sun Jun 14 17:27:25 2015 (r22739)
@@ -20,3 +20,9 @@
# Add upstream patches
+ bugfix/all/stable/2.6.32.66.patch
+
++ bugfix/all/udf-verify-i_size-when-loading-inode.patch
++ bugfix/all/udf-verify-symlink-size-before-loading-it.patch
++ bugfix/all/udf-treat-symlink-component-of-type-2-as.patch
++ bugfix/all/udf-check-path-length-when-reading-symlink.patch
++ bugfix/all/udf-check-component-length-before-reading-it.patch
More information about the Kernel-svn-changes
mailing list