hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/block/partitions/amiga.c
....@@ -11,10 +11,17 @@
1111 #define pr_fmt(fmt) fmt
1212
1313 #include <linux/types.h>
14
+#include <linux/mm_types.h>
15
+#include <linux/overflow.h>
1416 #include <linux/affs_hardblocks.h>
1517
1618 #include "check.h"
17
-#include "amiga.h"
19
+
20
+/* magic offsets in partition DosEnvVec */
21
+#define NR_HD 3
22
+#define NR_SECT 5
23
+#define LO_CYL 9
24
+#define HI_CYL 10
1825
1926 static __inline__ u32
2027 checksum_block(__be32 *m, int size)
....@@ -32,8 +39,12 @@
3239 unsigned char *data;
3340 struct RigidDiskBlock *rdb;
3441 struct PartitionBlock *pb;
35
- int start_sect, nr_sects, blk, part, res = 0;
36
- int blksize = 1; /* Multiplier for disk block size */
42
+ u64 start_sect, nr_sects;
43
+ sector_t blk, end_sect;
44
+ u32 cylblk; /* rdb_CylBlocks = nr_heads*sect_per_track */
45
+ u32 nr_hd, nr_sect, lo_cyl, hi_cyl;
46
+ int part, res = 0;
47
+ unsigned int blksize = 1; /* Multiplier for disk block size */
3748 int slot = 1;
3849 char b[BDEVNAME_SIZE];
3950
....@@ -42,9 +53,8 @@
4253 goto rdb_done;
4354 data = read_part_sector(state, blk, &sect);
4455 if (!data) {
45
- if (warn_no_part)
46
- pr_err("Dev %s: unable to read RDB block %d\n",
47
- bdevname(state->bdev, b), blk);
56
+ pr_err("Dev %s: unable to read RDB block %llu\n",
57
+ bdevname(state->bdev, b), blk);
4858 res = -1;
4959 goto rdb_done;
5060 }
....@@ -60,12 +70,12 @@
6070 *(__be32 *)(data+0xdc) = 0;
6171 if (checksum_block((__be32 *)data,
6272 be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
63
- pr_err("Trashed word at 0xd0 in block %d ignored in checksum calculation\n",
73
+ pr_err("Trashed word at 0xd0 in block %llu ignored in checksum calculation\n",
6474 blk);
6575 break;
6676 }
6777
68
- pr_err("Dev %s: RDB in block %d has bad checksum\n",
78
+ pr_err("Dev %s: RDB in block %llu has bad checksum\n",
6979 bdevname(state->bdev, b), blk);
7080 }
7181
....@@ -81,13 +91,17 @@
8191 }
8292 blk = be32_to_cpu(rdb->rdb_PartitionList);
8393 put_dev_sector(sect);
84
- for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
85
- blk *= blksize; /* Read in terms partition table understands */
94
+ for (part = 1; (s32) blk>0 && part<=16; part++, put_dev_sector(sect)) {
95
+ /* Read in terms partition table understands */
96
+ if (check_mul_overflow(blk, (sector_t) blksize, &blk)) {
97
+ pr_err("Dev %s: overflow calculating partition block %llu! Skipping partitions %u and beyond\n",
98
+ bdevname(state->bdev, b), blk, part);
99
+ break;
100
+ }
86101 data = read_part_sector(state, blk, &sect);
87102 if (!data) {
88
- if (warn_no_part)
89
- pr_err("Dev %s: unable to read partition block %d\n",
90
- bdevname(state->bdev, b), blk);
103
+ pr_err("Dev %s: unable to read partition block %llu\n",
104
+ bdevname(state->bdev, b), blk);
91105 res = -1;
92106 goto rdb_done;
93107 }
....@@ -98,19 +112,70 @@
98112 if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
99113 continue;
100114
101
- /* Tell Kernel about it */
115
+ /* RDB gives us more than enough rope to hang ourselves with,
116
+ * many times over (2^128 bytes if all fields max out).
117
+ * Some careful checks are in order, so check for potential
118
+ * overflows.
119
+ * We are multiplying four 32 bit numbers to one sector_t!
120
+ */
102121
103
- nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
104
- be32_to_cpu(pb->pb_Environment[9])) *
105
- be32_to_cpu(pb->pb_Environment[3]) *
106
- be32_to_cpu(pb->pb_Environment[5]) *
107
- blksize;
122
+ nr_hd = be32_to_cpu(pb->pb_Environment[NR_HD]);
123
+ nr_sect = be32_to_cpu(pb->pb_Environment[NR_SECT]);
124
+
125
+ /* CylBlocks is total number of blocks per cylinder */
126
+ if (check_mul_overflow(nr_hd, nr_sect, &cylblk)) {
127
+ pr_err("Dev %s: heads*sects %u overflows u32, skipping partition!\n",
128
+ bdevname(state->bdev, b), cylblk);
129
+ continue;
130
+ }
131
+
132
+ /* check for consistency with RDB defined CylBlocks */
133
+ if (cylblk > be32_to_cpu(rdb->rdb_CylBlocks)) {
134
+ pr_warn("Dev %s: cylblk %u > rdb_CylBlocks %u!\n",
135
+ bdevname(state->bdev, b), cylblk,
136
+ be32_to_cpu(rdb->rdb_CylBlocks));
137
+ }
138
+
139
+ /* RDB allows for variable logical block size -
140
+ * normalize to 512 byte blocks and check result.
141
+ */
142
+
143
+ if (check_mul_overflow(cylblk, blksize, &cylblk)) {
144
+ pr_err("Dev %s: partition %u bytes per cyl. overflows u32, skipping partition!\n",
145
+ bdevname(state->bdev, b), part);
146
+ continue;
147
+ }
148
+
149
+ /* Calculate partition start and end. Limit of 32 bit on cylblk
150
+ * guarantees no overflow occurs if LBD support is enabled.
151
+ */
152
+
153
+ lo_cyl = be32_to_cpu(pb->pb_Environment[LO_CYL]);
154
+ start_sect = ((u64) lo_cyl * cylblk);
155
+
156
+ hi_cyl = be32_to_cpu(pb->pb_Environment[HI_CYL]);
157
+ nr_sects = (((u64) hi_cyl - lo_cyl + 1) * cylblk);
158
+
108159 if (!nr_sects)
109160 continue;
110
- start_sect = be32_to_cpu(pb->pb_Environment[9]) *
111
- be32_to_cpu(pb->pb_Environment[3]) *
112
- be32_to_cpu(pb->pb_Environment[5]) *
113
- blksize;
161
+
162
+ /* Warn user if partition end overflows u32 (AmigaDOS limit) */
163
+
164
+ if ((start_sect + nr_sects) > UINT_MAX) {
165
+ pr_warn("Dev %s: partition %u (%llu-%llu) needs 64 bit device support!\n",
166
+ bdevname(state->bdev, b), part,
167
+ start_sect, start_sect + nr_sects);
168
+ }
169
+
170
+ if (check_add_overflow(start_sect, nr_sects, &end_sect)) {
171
+ pr_err("Dev %s: partition %u (%llu-%llu) needs LBD device support, skipping partition!\n",
172
+ bdevname(state->bdev, b), part,
173
+ start_sect, end_sect);
174
+ continue;
175
+ }
176
+
177
+ /* Tell Kernel about it */
178
+
114179 put_partition(state,slot++,start_sect,nr_sects);
115180 {
116181 /* Be even more informative to aid mounting */