From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751862AbbLJQOE (ORCPT ); Thu, 10 Dec 2015 11:14:04 -0500 Received: from aserp1040.oracle.com ([141.146.126.69]:35134 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750966AbbLJQOD (ORCPT ); Thu, 10 Dec 2015 11:14:03 -0500 From: Vegard Nossum To: Jan Kara Cc: linux-kernel@vger.kernel.org, quentin.casasnovas@oracle.com, Vegard Nossum Subject: [PATCH] udf: limit the maximum number of TD redirections Date: Thu, 10 Dec 2015 17:13:41 +0100 Message-Id: <1449764021-20609-1-git-send-email-vegard.nossum@oracle.com> X-Mailer: git-send-email 1.9.1 X-Source-IP: aserv0021.oracle.com [141.146.126.233] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Filesystem fuzzing revealed that we could get stuck in the udf_process_sequence() loop. The maximum limit was chosen arbitrarily but fixes the problem I saw. --- fs/udf/super.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git fs/udf/super.c fs/udf/super.c index 81155b9..fd45537 100644 --- fs/udf/super.c +++ fs/udf/super.c @@ -1586,6 +1586,13 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ } /* + * Maximum number of Terminating Descriptor redirections. The chosen number is + * arbitrary - just that we hopefully don't limit any real use of rewritten + * inode on write-once media but avoid looping for too long on corrupted media. + */ +#define UDF_MAX_TD_NESTING 64 + +/* * Process a main/reserve volume descriptor sequence. * @block First block of first extent of the sequence. * @lastblock Lastblock of first extent of the sequence. @@ -1609,6 +1616,7 @@ static noinline int udf_process_sequence( uint16_t ident; long next_s = 0, next_e = 0; int ret; + unsigned int indirections = 0; memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); @@ -1679,6 +1687,12 @@ static noinline int udf_process_sequence( } break; case TAG_IDENT_TD: /* ISO 13346 3/10.9 */ + if (++indirections > UDF_MAX_TD_NESTING) { + udf_err(sb, "too many TDs (max %u supported)\n", UDF_MAX_TD_NESTING); + brelse(bh); + return -EIO; + } + vds[VDS_POS_TERMINATING_DESC].block = block; if (next_e) { block = next_s; -- 1.9.1