]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Kay Sievers <kay.sievers@vrfy.org> |
2 | Date: Thu, 16 Oct 2008 05:04:21 +0000 (-0700) | |
3 | Subject: block: sanitize invalid partition table entries | |
4 | Git-commit: ac0d86f5809598ddcd6bfa0ea8245ccc910e9eac | |
5 | Patch-mainline: 2.6.28 | |
6 | References: bnc#371657 | |
7 | ||
8 | block: sanitize invalid partition table entries | |
9 | ||
10 | We currently follow blindly what the partition table lies about the | |
11 | disk, and let the kernel create block devices which can not be accessed. | |
12 | Trying to identify the device leads to kernel logs full of: | |
13 | sdb: rw=0, want=73392, limit=28800 | |
14 | attempt to access beyond end of device | |
15 | ||
16 | Here is an example of a broken partition table, where sda2 starts | |
17 | behind the end of the disk, and sdb3 is larger than the entire disk: | |
18 | Disk /dev/sdb: 14 MB, 14745600 bytes | |
19 | 1 heads, 29 sectors/track, 993 cylinders, total 28800 sectors | |
20 | Device Boot Start End Blocks Id System | |
21 | /dev/sdb1 29 7800 3886 83 Linux | |
22 | /dev/sdb2 37801 45601 3900+ 83 Linux | |
23 | /dev/sdb3 15602 73402 28900+ 83 Linux | |
24 | /dev/sdb4 23403 28796 2697 83 Linux | |
25 | ||
26 | The kernel creates these completely invalid devices, which can not be | |
27 | accessed, or may lead to other unpredictable failures: | |
28 | grep . /sys/class/block/sdb*/{start,size} | |
29 | /sys/class/block/sdb/size:28800 | |
30 | /sys/class/block/sdb1/start:29 | |
31 | /sys/class/block/sdb1/size:7772 | |
32 | /sys/class/block/sdb2/start:37801 | |
33 | /sys/class/block/sdb2/size:7801 | |
34 | /sys/class/block/sdb3/start:15602 | |
35 | /sys/class/block/sdb3/size:57801 | |
36 | /sys/class/block/sdb4/start:23403 | |
37 | /sys/class/block/sdb4/size:5394 | |
38 | ||
39 | With this patch, we ignore partitions which start behind the end of the disk, | |
40 | and limit partitions to the end of the disk if they pretend to be larger: | |
41 | grep . /sys/class/block/sdb*/{start,size} | |
42 | /sys/class/block/sdb/size:28800 | |
43 | /sys/class/block/sdb1/start:29 | |
44 | /sys/class/block/sdb1/size:7772 | |
45 | /sys/class/block/sdb3/start:15602 | |
46 | /sys/class/block/sdb3/size:13198 | |
47 | /sys/class/block/sdb4/start:23403 | |
48 | /sys/class/block/sdb4/size:5394 | |
49 | ||
50 | These warnings are printed to the kernel log: | |
51 | sdb: p2 ignored, start 37801 is behind the end of the disk | |
52 | sdb: p3 size 57801 limited to end of disk | |
53 | ||
54 | Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> | |
55 | Cc: Herton Ronaldo Krzesinski <herton@mandriva.com.br> | |
56 | Cc: Jens Axboe <jens.axboe@oracle.com> | |
57 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
58 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
59 | Acked-by: Jeff Mahoney <jeffm@suse.com> | |
60 | --- | |
61 | ||
62 | fs/partitions/check.c | 17 +++++++++++++++-- | |
63 | 1 file changed, 15 insertions(+), 2 deletions(-) | |
64 | ||
65 | --- a/fs/partitions/check.c | |
66 | +++ b/fs/partitions/check.c | |
67 | @@ -498,10 +498,23 @@ int rescan_partitions(struct gendisk *di | |
68 | sector_t from = state->parts[p].from; | |
69 | if (!size) | |
70 | continue; | |
71 | + if (from >= get_capacity(disk)) { | |
72 | + printk(KERN_WARNING | |
73 | + "%s: p%d ignored, start %llu is behind the end of the disk\n", | |
74 | + disk->disk_name, p, (unsigned long long) from); | |
75 | + continue; | |
76 | + } | |
77 | if (from + size > get_capacity(disk)) { | |
78 | + /* | |
79 | + * we can not ignore partitions of broken tables | |
80 | + * created by for example camera firmware, but we | |
81 | + * limit them to the end of the disk to avoid | |
82 | + * creating invalid block devices | |
83 | + */ | |
84 | printk(KERN_WARNING | |
85 | - "%s: p%d exceeds device capacity\n", | |
86 | - disk->disk_name, p); | |
87 | + "%s: p%d size %llu limited to end of disk\n", | |
88 | + disk->disk_name, p, (unsigned long long) size); | |
89 | + size = get_capacity(disk) - from; | |
90 | } | |
91 | res = add_partition(disk, p, from, size, state->parts[p].flags); | |
92 | if (res) { |