Re: [PATCH] block: fix Amiga partition support for disks >= 1 TB

Kars de Jong
2018-07-02T06:38:55Z

Op ma 2 jul. 2018 om 07:29 schreef Michael Schmitz <schmitzmic@gmail.com>:
> @@ -98,6 +101,79 @@ int amiga_partition(struct parsed_partitions *state)
> if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
> continue;
>
> + /* RDB gives us more than enough rope to hang ourselves with,
> + * many times over (2^128 bytes if all fields max out).
> + * Some careful checks are in order.
> + */
> +
> + /* CylBlocks is total number of blocks per cylinder */
> + cylblk = be32_to_cpu(pb->pb_Environment[3]) *
> + be32_to_cpu(pb->pb_Environment[5]);
> +

Could you please create #defines for all these magic offsets in pb_Environment?
Below are a few more.
This makes the code much more readable.
Thanks!

> + /* check for consistency with RDB defined CylBlocks */
> + if (cylblk > be32_to_cpu(rdb->rdb_CylBlocks)) {
> + pr_err("Dev %s: cylblk 0x%lx > rdb_CylBlocks 0x%x!\n",
> + bdevname(state->bdev, b),
> + (unsigned long) cylblk,
> + be32_to_cpu(rdb->rdb_CylBlocks));
> + }
> +
> + /* check for potential overflows - we are going to multiply
> + * three 32 bit numbers to one 64 bit result later!
> + * Condition 1: nr_heads * sects_per_track must fit u32!
> + * NB: This is a HARD limit for AmigaDOS. We don't care much.
> + */
> +
> + if (cylblk > UINT_MAX) {
> + pr_err("Dev %s: hds*sects 0x%lx > UINT_MAX!\n",
> + bdevname(state->bdev, b),
> + (unsigned long) cylblk);
> +
> + /* lop off low 32 bits */
> + cylblk_res = cylblk >> 32;
> +
> + /* check for further overflow in end result */
> + if (be32_to_cpu(pb->pb_Environment[9]) *
> + cylblk_res * blksize > UINT_MAX) {
> + pr_err("Dev %s: start_sect overflows u64!\n",
> + bdevname(state->bdev, b));
> + res = -1;
> + goto rdb_done;
> + }
> +
> + if (be32_to_cpu(pb->pb_Environment[10]) *
> + cylblk_res * blksize > UINT_MAX) {
> + pr_err("Dev %s: end_sect overflows u64!\n",
> + bdevname(state->bdev, b));
> + res = -1;
> + goto rdb_done;
> + }
> + }
> +
> + /* Condition 2: even if CylBlocks did not overflow, the end
> + * result must still fit u64!
> + */
> +
> + /* how many bits above 32 in cylblk * blksize ? */
> + if (cylblk*blksize > (u64) UINT_MAX)
> + blk_shift = ilog2(cylblk*blksize) - 32;
> +
> + if (be32_to_cpu(pb->pb_Environment[9])
> + > (u64) UINT_MAX>>blk_shift) {
> + pr_err("Dev %s: start_sect overflows u64!\n",
> + bdevname(state->bdev, b));
> + res = -1;
> + goto rdb_done;
> + }
> +
> + if (be32_to_cpu(pb->pb_Environment[10])
> + > (u64) UINT_MAX>>blk_shift) {
> + pr_err("Dev %s: end_sect overflows u64!\n",
> + bdevname(state->bdev, b));
> + res = -1;
> + goto rdb_done;
> + }
> +
> /* Tell Kernel about it */
>
> nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -