diff mbox

[2/6] udf: Simplify handling of Volume Descriptor Pointers

Message ID 20180214102850.28755-3-jack@suse.cz (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Kara Feb. 14, 2018, 10:28 a.m. UTC
According to ECMA-167 3/8.4.2 Volume Descriptor Pointer is terminating
current extent of Volume Descriptor Sequence. Also according to ECMA-167
3/8.4.3 Volume Descriptor Sequence Number is not significant for Volume
Descriptor Pointers. Simplify the handling of Volume Descriptor Pointers
to take this into account.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/udf/super.c | 41 ++++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

Comments

Pali Rohár Feb. 14, 2018, 5:26 p.m. UTC | #1
On Wednesday 14 February 2018 11:28:46 Jan Kara wrote:
> According to ECMA-167 3/8.4.2 Volume Descriptor Pointer is terminating
> current extent of Volume Descriptor Sequence. Also according to ECMA-167
> 3/8.4.3 Volume Descriptor Sequence Number is not significant for Volume
> Descriptor Pointers. Simplify the handling of Volume Descriptor Pointers
> to take this into account.
> 
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
>  fs/udf/super.c | 41 ++++++++++++++++-------------------------
>  1 file changed, 16 insertions(+), 25 deletions(-)
> 
> diff --git a/fs/udf/super.c b/fs/udf/super.c
> index 5c5d5fd513cc..f80b97173acd 100644
> --- a/fs/udf/super.c
> +++ b/fs/udf/super.c
> @@ -1615,7 +1615,6 @@ static noinline int udf_process_sequence(
>  	bool done = false;
>  	uint32_t vdsn;
>  	uint16_t ident;
> -	long next_s = 0, next_e = 0;
>  	int ret;
>  	unsigned int indirections = 0;
>  
> @@ -1647,19 +1646,22 @@ static noinline int udf_process_sequence(
>  			}
>  			break;
>  		case TAG_IDENT_VDP: /* ISO 13346 3/10.3 */
> -			curr = &vds[VDS_POS_VOL_DESC_PTR];
> -			if (vdsn >= curr->volDescSeqNum) {
> -				curr->volDescSeqNum = vdsn;
> -				curr->block = block;
> -
> -				vdp = (struct volDescPtr *)bh->b_data;
> -				next_s = le32_to_cpu(
> -					vdp->nextVolDescSeqExt.extLocation);
> -				next_e = le32_to_cpu(
> -					vdp->nextVolDescSeqExt.extLength);
> -				next_e = next_e >> sb->s_blocksize_bits;
> -				next_e += next_s - 1;
> +			if (++indirections > UDF_MAX_TD_NESTING) {
> +				udf_err(sb, "too many Volume Descriptor "
> +					"Pointers (max %u supported)\n",
> +					UDF_MAX_TD_NESTING);
> +				brelse(bh);
> +				return -EIO;
>  			}
> +
> +			vdp = (struct volDescPtr *)bh->b_data;
> +			block = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation);

Another pathological case: disc with two (or more) VDP descriptors and
each points to another in cycle.

Seems that this would not cause infinite loop due to
UDF_MAX_TD_NESTING, but probably can cause some troubles.

> +			lastblock = le32_to_cpu(
> +				vdp->nextVolDescSeqExt.extLength) >>
> +				sb->s_blocksize_bits;
> +			lastblock += block - 1;
> +			/* For loop is going to increment 'block' again */
> +			block--;
>  			break;
>  		case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */
>  			curr = &vds[VDS_POS_IMP_USE_VOL_DESC];
> @@ -1688,19 +1690,8 @@ 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;
> -				lastblock = next_e;
> -				next_s = next_e = 0;
> -			} else
> -				done = true;
> +			done = true;
>  			break;
>  		}
>  		brelse(bh);
Jan Kara Feb. 15, 2018, 8:43 a.m. UTC | #2
On Wed 14-02-18 18:26:03, Pali Rohár wrote:
> On Wednesday 14 February 2018 11:28:46 Jan Kara wrote:
> > According to ECMA-167 3/8.4.2 Volume Descriptor Pointer is terminating
> > current extent of Volume Descriptor Sequence. Also according to ECMA-167
> > 3/8.4.3 Volume Descriptor Sequence Number is not significant for Volume
> > Descriptor Pointers. Simplify the handling of Volume Descriptor Pointers
> > to take this into account.
> > 
> > Signed-off-by: Jan Kara <jack@suse.cz>
> > ---
> >  fs/udf/super.c | 41 ++++++++++++++++-------------------------
> >  1 file changed, 16 insertions(+), 25 deletions(-)
> > 
> > diff --git a/fs/udf/super.c b/fs/udf/super.c
> > index 5c5d5fd513cc..f80b97173acd 100644
> > --- a/fs/udf/super.c
> > +++ b/fs/udf/super.c
> > @@ -1615,7 +1615,6 @@ static noinline int udf_process_sequence(
> >  	bool done = false;
> >  	uint32_t vdsn;
> >  	uint16_t ident;
> > -	long next_s = 0, next_e = 0;
> >  	int ret;
> >  	unsigned int indirections = 0;
> >  
> > @@ -1647,19 +1646,22 @@ static noinline int udf_process_sequence(
> >  			}
> >  			break;
> >  		case TAG_IDENT_VDP: /* ISO 13346 3/10.3 */
> > -			curr = &vds[VDS_POS_VOL_DESC_PTR];
> > -			if (vdsn >= curr->volDescSeqNum) {
> > -				curr->volDescSeqNum = vdsn;
> > -				curr->block = block;
> > -
> > -				vdp = (struct volDescPtr *)bh->b_data;
> > -				next_s = le32_to_cpu(
> > -					vdp->nextVolDescSeqExt.extLocation);
> > -				next_e = le32_to_cpu(
> > -					vdp->nextVolDescSeqExt.extLength);
> > -				next_e = next_e >> sb->s_blocksize_bits;
> > -				next_e += next_s - 1;
> > +			if (++indirections > UDF_MAX_TD_NESTING) {
> > +				udf_err(sb, "too many Volume Descriptor "
> > +					"Pointers (max %u supported)\n",
> > +					UDF_MAX_TD_NESTING);
> > +				brelse(bh);
> > +				return -EIO;
> >  			}
> > +
> > +			vdp = (struct volDescPtr *)bh->b_data;
> > +			block = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation);
> 
> Another pathological case: disc with two (or more) VDP descriptors and
> each points to another in cycle.
> 
> Seems that this would not cause infinite loop due to
> UDF_MAX_TD_NESTING, but probably can cause some troubles.

Yes. Such disk is invalid so our only goal is not to crash / livelock the
kernel and UDF_MAX_TD_NESTING protection is enough for that.

								Honza
Pali Rohár Feb. 15, 2018, 10:33 p.m. UTC | #3
On Thursday 15 February 2018 09:43:12 Jan Kara wrote:
> On Wed 14-02-18 18:26:03, Pali Rohár wrote:
> > On Wednesday 14 February 2018 11:28:46 Jan Kara wrote:
> > > According to ECMA-167 3/8.4.2 Volume Descriptor Pointer is terminating
> > > current extent of Volume Descriptor Sequence. Also according to ECMA-167
> > > 3/8.4.3 Volume Descriptor Sequence Number is not significant for Volume
> > > Descriptor Pointers. Simplify the handling of Volume Descriptor Pointers
> > > to take this into account.
> > > 
> > > Signed-off-by: Jan Kara <jack@suse.cz>
> > > ---
> > >  fs/udf/super.c | 41 ++++++++++++++++-------------------------
> > >  1 file changed, 16 insertions(+), 25 deletions(-)
> > > 
> > > diff --git a/fs/udf/super.c b/fs/udf/super.c
> > > index 5c5d5fd513cc..f80b97173acd 100644
> > > --- a/fs/udf/super.c
> > > +++ b/fs/udf/super.c
> > > @@ -1615,7 +1615,6 @@ static noinline int udf_process_sequence(
> > >  	bool done = false;
> > >  	uint32_t vdsn;
> > >  	uint16_t ident;
> > > -	long next_s = 0, next_e = 0;
> > >  	int ret;
> > >  	unsigned int indirections = 0;
> > >  
> > > @@ -1647,19 +1646,22 @@ static noinline int udf_process_sequence(
> > >  			}
> > >  			break;
> > >  		case TAG_IDENT_VDP: /* ISO 13346 3/10.3 */
> > > -			curr = &vds[VDS_POS_VOL_DESC_PTR];
> > > -			if (vdsn >= curr->volDescSeqNum) {
> > > -				curr->volDescSeqNum = vdsn;
> > > -				curr->block = block;
> > > -
> > > -				vdp = (struct volDescPtr *)bh->b_data;
> > > -				next_s = le32_to_cpu(
> > > -					vdp->nextVolDescSeqExt.extLocation);
> > > -				next_e = le32_to_cpu(
> > > -					vdp->nextVolDescSeqExt.extLength);
> > > -				next_e = next_e >> sb->s_blocksize_bits;
> > > -				next_e += next_s - 1;
> > > +			if (++indirections > UDF_MAX_TD_NESTING) {
> > > +				udf_err(sb, "too many Volume Descriptor "
> > > +					"Pointers (max %u supported)\n",
> > > +					UDF_MAX_TD_NESTING);
> > > +				brelse(bh);
> > > +				return -EIO;
> > >  			}
> > > +
> > > +			vdp = (struct volDescPtr *)bh->b_data;
> > > +			block = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation);
> > 
> > Another pathological case: disc with two (or more) VDP descriptors and
> > each points to another in cycle.
> > 
> > Seems that this would not cause infinite loop due to
> > UDF_MAX_TD_NESTING, but probably can cause some troubles.
> 
> Yes. Such disk is invalid so our only goal is not to crash / livelock the
> kernel and UDF_MAX_TD_NESTING protection is enough for that.

Ok, then you can add my Acked-by on whole patch series.

Acked-by: Pali Rohár <pali.rohar@gmail.com>
Jan Kara Feb. 16, 2018, 10:16 a.m. UTC | #4
On Thu 15-02-18 23:33:16, Pali Rohár wrote:
> On Thursday 15 February 2018 09:43:12 Jan Kara wrote:
> > On Wed 14-02-18 18:26:03, Pali Rohár wrote:
> > > On Wednesday 14 February 2018 11:28:46 Jan Kara wrote:
> > > > According to ECMA-167 3/8.4.2 Volume Descriptor Pointer is terminating
> > > > current extent of Volume Descriptor Sequence. Also according to ECMA-167
> > > > 3/8.4.3 Volume Descriptor Sequence Number is not significant for Volume
> > > > Descriptor Pointers. Simplify the handling of Volume Descriptor Pointers
> > > > to take this into account.
> > > > 
> > > > Signed-off-by: Jan Kara <jack@suse.cz>
> > > > ---
> > > >  fs/udf/super.c | 41 ++++++++++++++++-------------------------
> > > >  1 file changed, 16 insertions(+), 25 deletions(-)
> > > > 
> > > > diff --git a/fs/udf/super.c b/fs/udf/super.c
> > > > index 5c5d5fd513cc..f80b97173acd 100644
> > > > --- a/fs/udf/super.c
> > > > +++ b/fs/udf/super.c
> > > > @@ -1615,7 +1615,6 @@ static noinline int udf_process_sequence(
> > > >  	bool done = false;
> > > >  	uint32_t vdsn;
> > > >  	uint16_t ident;
> > > > -	long next_s = 0, next_e = 0;
> > > >  	int ret;
> > > >  	unsigned int indirections = 0;
> > > >  
> > > > @@ -1647,19 +1646,22 @@ static noinline int udf_process_sequence(
> > > >  			}
> > > >  			break;
> > > >  		case TAG_IDENT_VDP: /* ISO 13346 3/10.3 */
> > > > -			curr = &vds[VDS_POS_VOL_DESC_PTR];
> > > > -			if (vdsn >= curr->volDescSeqNum) {
> > > > -				curr->volDescSeqNum = vdsn;
> > > > -				curr->block = block;
> > > > -
> > > > -				vdp = (struct volDescPtr *)bh->b_data;
> > > > -				next_s = le32_to_cpu(
> > > > -					vdp->nextVolDescSeqExt.extLocation);
> > > > -				next_e = le32_to_cpu(
> > > > -					vdp->nextVolDescSeqExt.extLength);
> > > > -				next_e = next_e >> sb->s_blocksize_bits;
> > > > -				next_e += next_s - 1;
> > > > +			if (++indirections > UDF_MAX_TD_NESTING) {
> > > > +				udf_err(sb, "too many Volume Descriptor "
> > > > +					"Pointers (max %u supported)\n",
> > > > +					UDF_MAX_TD_NESTING);
> > > > +				brelse(bh);
> > > > +				return -EIO;
> > > >  			}
> > > > +
> > > > +			vdp = (struct volDescPtr *)bh->b_data;
> > > > +			block = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation);
> > > 
> > > Another pathological case: disc with two (or more) VDP descriptors and
> > > each points to another in cycle.
> > > 
> > > Seems that this would not cause infinite loop due to
> > > UDF_MAX_TD_NESTING, but probably can cause some troubles.
> > 
> > Yes. Such disk is invalid so our only goal is not to crash / livelock the
> > kernel and UDF_MAX_TD_NESTING protection is enough for that.
> 
> Ok, then you can add my Acked-by on whole patch series.
> 
> Acked-by: Pali Rohár <pali.rohar@gmail.com>

Thanks for review!

								Honza
diff mbox

Patch

diff --git a/fs/udf/super.c b/fs/udf/super.c
index 5c5d5fd513cc..f80b97173acd 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1615,7 +1615,6 @@  static noinline int udf_process_sequence(
 	bool done = false;
 	uint32_t vdsn;
 	uint16_t ident;
-	long next_s = 0, next_e = 0;
 	int ret;
 	unsigned int indirections = 0;
 
@@ -1647,19 +1646,22 @@  static noinline int udf_process_sequence(
 			}
 			break;
 		case TAG_IDENT_VDP: /* ISO 13346 3/10.3 */
-			curr = &vds[VDS_POS_VOL_DESC_PTR];
-			if (vdsn >= curr->volDescSeqNum) {
-				curr->volDescSeqNum = vdsn;
-				curr->block = block;
-
-				vdp = (struct volDescPtr *)bh->b_data;
-				next_s = le32_to_cpu(
-					vdp->nextVolDescSeqExt.extLocation);
-				next_e = le32_to_cpu(
-					vdp->nextVolDescSeqExt.extLength);
-				next_e = next_e >> sb->s_blocksize_bits;
-				next_e += next_s - 1;
+			if (++indirections > UDF_MAX_TD_NESTING) {
+				udf_err(sb, "too many Volume Descriptor "
+					"Pointers (max %u supported)\n",
+					UDF_MAX_TD_NESTING);
+				brelse(bh);
+				return -EIO;
 			}
+
+			vdp = (struct volDescPtr *)bh->b_data;
+			block = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation);
+			lastblock = le32_to_cpu(
+				vdp->nextVolDescSeqExt.extLength) >>
+				sb->s_blocksize_bits;
+			lastblock += block - 1;
+			/* For loop is going to increment 'block' again */
+			block--;
 			break;
 		case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */
 			curr = &vds[VDS_POS_IMP_USE_VOL_DESC];
@@ -1688,19 +1690,8 @@  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;
-				lastblock = next_e;
-				next_s = next_e = 0;
-			} else
-				done = true;
+			done = true;
 			break;
 		}
 		brelse(bh);