summaryrefslogtreecommitdiff
path: root/fs/udf/super.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-15 11:51:51 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-15 11:51:51 -0800
commit1d3671df72e0fe28d7cc686cb432e87c06f4accc (patch)
tree75bf9bdc327bd12d7ed0ca6ee5d1b0254c4753a4 /fs/udf/super.c
parent875fc4f5ddf35605581f9a5900c14afef48611f2 (diff)
parentbb00c898ad1ce40c4bb422a8207ae562e9aea7ae (diff)
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull UDF fixes and quota cleanups from Jan Kara: "Several UDF fixes and some minor quota cleanups" * 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: udf: Check output buffer length when converting name to CS0 udf: Prevent buffer overrun with multi-byte characters quota: constify qtree_fmt_operations structures udf: avoid uninitialized variable use udf: Fix lost indirect extent block udf: Factor out code for creating indirect extent udf: limit the maximum number of indirect extents in a row udf: limit the maximum number of TD redirections fs: make quota/dquot.c explicitly non-modular fs: make quota/netlink.c explicitly non-modular
Diffstat (limited to 'fs/udf/super.c')
-rw-r--r--fs/udf/super.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 9c64a3ca9837..0fbb4c7c72e8 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1587,6 +1587,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.
@@ -1610,6 +1617,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);
@@ -1680,6 +1688,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;