From patchwork Mon Jul 30 19:30:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Conklin X-Patchwork-Id: 174080 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 9E6D32C00A1 for ; Tue, 31 Jul 2012 05:30:48 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1Svvfq-0002Ic-7i; Mon, 30 Jul 2012 19:30:38 +0000 Received: from mail-qc0-f177.google.com ([209.85.216.177]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1Svvfm-0002I2-TJ for kernel-team@lists.ubuntu.com; Mon, 30 Jul 2012 19:30:35 +0000 Received: by mail-qc0-f177.google.com with SMTP id u28so3620869qcs.8 for ; Mon, 30 Jul 2012 12:30:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=oOJJqjPL1Q0XCVtD5WloA7rQ/vdPgjIccqgBgIgzAEc=; b=gsSmXjmLhXMj2Tq3tO5PeS1n1qtyHeLffoL3OcBhey2M/8SC1UZRLRPNjEFKs8fzKr lbcjZg4+YtOo9Qc09pOoHGXIPfl9UMnEY/O4wGfPjf7n1+D6Q0kQvmTF5A3jRutxu0rx 5i/4I/jENv5w4qalApRybYAg/Jmf6RNnfXLgNBkEGTiSZnm0ISHPeYrRNiNfu6yy07as OPuf8B+t6icEcJBHfV1RQJUEj6vrOca4Nb9Cij9xiLnslh0utdnaZxR78gWdrnvMkb/w PVFI+fI5KE4RV8GPXzOPlc9BiLKVEZiVV4CPKh2wGO7B6TifS4/CbG88I+Fro0aWC4Nl a3hQ== Received: by 10.224.178.73 with SMTP id bl9mr24946046qab.89.1343676634613; Mon, 30 Jul 2012 12:30:34 -0700 (PDT) Received: from localhost.localdomain (user-69-73-1-154.knology.net. [69.73.1.154]) by mx.google.com with ESMTPS id dr6sm8610265qab.16.2012.07.30.12.30.33 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 30 Jul 2012 12:30:34 -0700 (PDT) From: Steve Conklin To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/2] udf: Fortify loading of sparing table Date: Mon, 30 Jul 2012 14:30:06 -0500 Message-Id: <1343676607-31153-2-git-send-email-sconklin@canonical.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1343676607-31153-1-git-send-email-sconklin@canonical.com> References: <1343676607-31153-1-git-send-email-sconklin@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Jan Kara CVE-2012-3400 BugLink: http://bugs.launchpad.net/bugs/1024497 Backported with changes to error prints from upstream commit 1df2ae31c724e57be9d7ac00d78db8a5dabdd050 Add sanity checks when loading sparing table from disk to avoid accessing unallocated memory or writing to it. Signed-off-by: Jan Kara Signed-off-by: Steve Conklin --- fs/udf/super.c | 86 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 7b27b06..4ea5ad8 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include "udf_sb.h" @@ -1244,11 +1245,59 @@ out_bh: return ret; } +static int udf_load_sparable_map(struct super_block *sb, + struct udf_part_map *map, + struct sparablePartitionMap *spm) +{ + uint32_t loc; + uint16_t ident; + struct sparingTable *st; + struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing; + int i; + struct buffer_head *bh; + + map->s_partition_type = UDF_SPARABLE_MAP15; + sdata->s_packet_len = le16_to_cpu(spm->packetLength); + if (!is_power_of_2(sdata->s_packet_len)) { + udf_error(sb, __func__, + "error loading logical volume descriptor: Invalid packet length %u\n", + (unsigned)sdata->s_packet_len); + return -EIO; + } + if (spm->numSparingTables > 4) { + udf_error(sb, __func__, + "error loading logical volume descriptor: Too many sparing tables (%d)\n", + (int)spm->numSparingTables); + return -EIO; + } + + for (i = 0; i < spm->numSparingTables; i++) { + loc = le32_to_cpu(spm->locSparingTable[i]); + bh = udf_read_tagged(sb, loc, loc, &ident); + if (!bh) + continue; + + st = (struct sparingTable *)bh->b_data; + if (ident != 0 || + strncmp(st->sparingIdent.ident, UDF_ID_SPARING, + strlen(UDF_ID_SPARING)) || + sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > + sb->s_blocksize) { + brelse(bh); + continue; + } + + sdata->s_spar_map[i] = bh; + } + map->s_partition_func = udf_get_pblock_spar15; + return 0; +} + static int udf_load_logicalvol(struct super_block *sb, sector_t block, struct kernel_lb_addr *fileset) { struct logicalVolDesc *lvd; - int i, j, offset; + int i, offset; uint8_t type; struct udf_sb_info *sbi = UDF_SB(sb); struct genericPartitionMap *gpm; @@ -1304,38 +1353,9 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, } else if (!strncmp(upm2->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { - uint32_t loc; - struct sparingTable *st; - struct sparablePartitionMap *spm = - (struct sparablePartitionMap *)gpm; - - map->s_partition_type = UDF_SPARABLE_MAP15; - map->s_type_specific.s_sparing.s_packet_len = - le16_to_cpu(spm->packetLength); - for (j = 0; j < spm->numSparingTables; j++) { - struct buffer_head *bh2; - - loc = le32_to_cpu( - spm->locSparingTable[j]); - bh2 = udf_read_tagged(sb, loc, loc, - &ident); - map->s_type_specific.s_sparing. - s_spar_map[j] = bh2; - - if (bh2 == NULL) - continue; - - st = (struct sparingTable *)bh2->b_data; - if (ident != 0 || strncmp( - st->sparingIdent.ident, - UDF_ID_SPARING, - strlen(UDF_ID_SPARING))) { - brelse(bh2); - map->s_type_specific.s_sparing. - s_spar_map[j] = NULL; - } - } - map->s_partition_func = udf_get_pblock_spar15; + if (udf_load_sparable_map(sb, map, + (struct sparablePartitionMap *)gpm) < 0) + goto out_bh; } else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA))) {