From patchwork Wed May 18 21:09:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alden Tondettar X-Patchwork-Id: 9122481 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 4B812BF29F for ; Wed, 18 May 2016 21:13:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4E363202EC for ; Wed, 18 May 2016 21:13:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 42604202AE for ; Wed, 18 May 2016 21:13:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753691AbcERVM4 (ORCPT ); Wed, 18 May 2016 17:12:56 -0400 Received: from mail-pa0-f67.google.com ([209.85.220.67]:33457 "EHLO mail-pa0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754181AbcERVMb (ORCPT ); Wed, 18 May 2016 17:12:31 -0400 Received: by mail-pa0-f67.google.com with SMTP id gh9so5842919pac.0; Wed, 18 May 2016 14:12:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4fDPEHGDzIjubbvl5/yPsolfOqnmvAQQrIDbjODQg7M=; b=Hf3h7iC2lBmLQJQlZTtmS3Ysq7al3ocHKhO6mjFyow/nJhJdiO7GmvIOo02eq0vjR3 P68U8P4lftdwHz24E2hRlQWybYhrV4s6xZX2Wjx+Nhbed/rEHnetuonBCGfhKpiHXxkE W7DkkNcxCGF4GesAvPMfOZD0MOFF3y+Lyb8r0v/q1WxTwyajd33bdUfj+yKHxRhaFN0/ za1gGLb8ZUZ2/cy1tDoSxaCUOYQ7GKqj6m8eO+v8bk0w/vh7tFREJAh6C3GgT9hQDLF8 0XcrrMChsyn5oMqv04xN3e/zeL4waGvap6de/er9/qcrSpGmhSqdWZyHZFHIKWXK+Doj cvPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4fDPEHGDzIjubbvl5/yPsolfOqnmvAQQrIDbjODQg7M=; b=Oohrytoxv8ZqPAs4Nxdifao76gO+gLbLxvK6KlTl/zK7vJctDV/xP797mhwxxvDLTs rsSa4qm6joTWkkX2rYt/2nHcNRdPNaqQOjG1wAjRNh0FBPBBH1vz+S54dUsCjyg2sgEG R6UBWNccaqhweeiPK8uQ32gsM/1rMZsQYFEbKwW02ZGjEyaAu/68tpEEG/zybR6nR5KN 568hRDjI0D3tLku8UUpq47qAhtIm7+TZbZwDtSPSrdvI+1DTHGSRmBoSZVS7fRNC0xXw D4N2xgdtFVVbaTrcv1z+swpGIC6/7dhkKhn/7TFVjFkX6IPxR+Q0XXofKbLIHG8fRAp5 zVVw== X-Gm-Message-State: AOPr4FWqGWMwffMbviCPmn+aA1P+r/dT5juM1vfAXzZBQGAFFseaNPL0nMLtnFXInZ1DHw== X-Received: by 10.67.3.200 with SMTP id by8mr13838382pad.13.1463605950115; Wed, 18 May 2016 14:12:30 -0700 (PDT) Received: from rincewind.rincewind (71.sub-75-211-163.myvzw.com. [75.211.163.71]) by smtp.gmail.com with ESMTPSA id az6sm14387898pab.43.2016.05.18.14.12.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 May 2016 14:12:28 -0700 (PDT) From: Alden Tondettar To: Jan Kara Cc: Laura Abbott , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Alden Tondettar Subject: [PATCH 3/3] udf: Use correct partition reference number for metadata Date: Wed, 18 May 2016 14:09:19 -0700 Message-Id: <1463605759-7616-5-git-send-email-alden.tondettar@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1463605759-7616-1-git-send-email-alden.tondettar@gmail.com> References: <1463605759-7616-1-git-send-email-alden.tondettar@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-8.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP UDF/OSTA terminology is confusing. Partition Numbers (PNs) are arbitrary 16-bit values, one for each physical partition in the volume. Partition Reference Numbers (PRNs) are indices into the the Partition Map Table and do not necessarily equal the PN of the mapped partition. The current metadata code mistakenly uses the PN instead of the PRN when mapping metadata blocks to physical/sparable blocks. Windows-created UDF 2.5 discs for some reason use large, arbitrary PNs, resulting in mount failure and KASAN read warnings in udf_read_inode(). For example, a NetBSD UDF 2.5 partition might look like this: PRN PN Type --- -- ---- 0 0 Sparable 1 0 Metadata Since PRN == PN, we are fine. But Windows could gives us: PRN PN Type --- ---- ---- 0 8192 Sparable 1 8192 Metadata So udf_read_inode() will start out by checking the partition length in sbi->s_partmaps[8192], which is obviously out of bounds. Fix this by creating a new field (s_partition_ref) in struct udf_meta_data, referencing whatever physical or sparable map has the same partition number as the metadata partition. Signed-off-by: Alden Tondettar --- fs/udf/partition.c | 6 ++++-- fs/udf/super.c | 22 ++++++++++++---------- fs/udf/udf_sb.h | 1 + 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/fs/udf/partition.c b/fs/udf/partition.c index ca3cde3..5960149 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c @@ -295,7 +295,8 @@ static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, map = &UDF_SB(sb)->s_partmaps[partition]; /* map to sparable/physical partition desc */ phyblock = udf_get_pblock(sb, eloc.logicalBlockNum, - map->s_partition_num, ext_offset + offset); + map->s_type_specific.s_metadata.s_partition_ref, + ext_offset + offset); } brelse(epos.bh); @@ -325,7 +326,8 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block, udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n"); if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) { mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, - mdata->s_mirror_file_loc, map->s_partition_num); + mdata->s_mirror_file_loc, + mdata->s_partition_ref); if (IS_ERR(mdata->s_mirror_fe)) mdata->s_mirror_fe = NULL; mdata->s_flags |= MF_MIRROR_FE_LOADED; diff --git a/fs/udf/super.c b/fs/udf/super.c index 5e2c8c8..26b6bf1 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -951,13 +951,13 @@ out2: } struct inode *udf_find_metadata_inode_efe(struct super_block *sb, - u32 meta_file_loc, u32 partition_num) + u32 meta_file_loc, u32 partition_ref) { struct kernel_lb_addr addr; struct inode *metadata_fe; addr.logicalBlockNum = meta_file_loc; - addr.partitionReferenceNum = partition_num; + addr.partitionReferenceNum = partition_ref; metadata_fe = udf_iget_special(sb, &addr); @@ -974,7 +974,8 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb, return metadata_fe; } -static int udf_load_metadata_files(struct super_block *sb, int partition) +static int udf_load_metadata_files(struct super_block *sb, int partition, + int type1_index) { struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map; @@ -984,20 +985,21 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) map = &sbi->s_partmaps[partition]; mdata = &map->s_type_specific.s_metadata; + mdata->s_partition_ref = type1_index; /* metadata address */ udf_debug("Metadata file location: block = %d part = %d\n", - mdata->s_meta_file_loc, map->s_partition_num); + mdata->s_meta_file_loc, mdata->s_partition_ref); fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc, - map->s_partition_num); + mdata->s_partition_ref); if (IS_ERR(fe)) { /* mirror file entry */ udf_debug("Mirror metadata file location: block = %d part = %d\n", - mdata->s_mirror_file_loc, map->s_partition_num); + mdata->s_mirror_file_loc, mdata->s_partition_ref); fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc, - map->s_partition_num); + mdata->s_partition_ref); if (IS_ERR(fe)) { udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n"); @@ -1015,7 +1017,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) */ if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) { addr.logicalBlockNum = mdata->s_bitmap_file_loc; - addr.partitionReferenceNum = map->s_partition_num; + addr.partitionReferenceNum = mdata->s_partition_ref; udf_debug("Bitmap file location: block = %d part = %d\n", addr.logicalBlockNum, addr.partitionReferenceNum); @@ -1283,7 +1285,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) p = (struct partitionDesc *)bh->b_data; partitionNumber = le16_to_cpu(p->partitionNumber); - /* First scan for TYPE1, SPARABLE and METADATA partitions */ + /* First scan for TYPE1 and SPARABLE partitions */ for (i = 0; i < sbi->s_partitions; i++) { map = &sbi->s_partmaps[i]; udf_debug("Searching map: (%d == %d)\n", @@ -1333,7 +1335,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) goto out_bh; if (map->s_partition_type == UDF_METADATA_MAP25) { - ret = udf_load_metadata_files(sb, i); + ret = udf_load_metadata_files(sb, i, type1_idx); if (ret < 0) { udf_err(sb, "error loading MetaData partition map %d\n", i); diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 27b5335..51e6de0 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -61,6 +61,7 @@ struct udf_meta_data { __u32 s_bitmap_file_loc; __u32 s_alloc_unit_size; __u16 s_align_unit_size; + __u16 s_partition_ref; int s_flags; struct inode *s_metadata_fe; struct inode *s_mirror_fe;