aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-raid.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2013-03-01 17:45:44 -0500
committerAlasdair G Kergon <agk@redhat.com>2013-03-01 17:45:44 -0500
commitfd7c092e711ebab55b2688d3859d95dfd0301f73 (patch)
tree3cc99f96f4a2de8e22347feb86b0ecd5dd7200d0 /drivers/md/dm-raid.c
parent16245bdc9d3e22d1460341a655c8b5288953bc14 (diff)
dm: fix truncated status strings
Avoid returning a truncated table or status string instead of setting the DM_BUFFER_FULL_FLAG when the last target of a table fills the buffer. When processing a table or status request, the function retrieve_status calls ti->type->status. If ti->type->status returns non-zero, retrieve_status assumes that the buffer overflowed and sets DM_BUFFER_FULL_FLAG. However, targets don't return non-zero values from their status method on overflow. Most targets returns always zero. If a buffer overflow happens in a target that is not the last in the table, it gets noticed during the next iteration of the loop in retrieve_status; but if a buffer overflow happens in the last target, it goes unnoticed and erroneously truncated data is returned. In the current code, the targets behave in the following way: * dm-crypt returns -ENOMEM if there is not enough space to store the key, but it returns 0 on all other overflows. * dm-thin returns errors from the status method if a disk error happened. This is incorrect because retrieve_status doesn't check the error code, it assumes that all non-zero values mean buffer overflow. * all the other targets always return 0. This patch changes the ti->type->status function to return void (because most targets don't use the return code). Overflow is detected in retrieve_status: if the status method fills up the remaining space completely, it is assumed that buffer overflow happened. Cc: stable@vger.kernel.org Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r--drivers/md/dm-raid.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 9e58dbd8d8cb..5a578d89da2d 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1201,8 +1201,8 @@ static int raid_map(struct dm_target *ti, struct bio *bio)
1201 return DM_MAPIO_SUBMITTED; 1201 return DM_MAPIO_SUBMITTED;
1202} 1202}
1203 1203
1204static int raid_status(struct dm_target *ti, status_type_t type, 1204static void raid_status(struct dm_target *ti, status_type_t type,
1205 unsigned status_flags, char *result, unsigned maxlen) 1205 unsigned status_flags, char *result, unsigned maxlen)
1206{ 1206{
1207 struct raid_set *rs = ti->private; 1207 struct raid_set *rs = ti->private;
1208 unsigned raid_param_cnt = 1; /* at least 1 for chunksize */ 1208 unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
@@ -1344,8 +1344,6 @@ static int raid_status(struct dm_target *ti, status_type_t type,
1344 DMEMIT(" -"); 1344 DMEMIT(" -");
1345 } 1345 }
1346 } 1346 }
1347
1348 return 0;
1349} 1347}
1350 1348
1351static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) 1349static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
@@ -1405,7 +1403,7 @@ static void raid_resume(struct dm_target *ti)
1405 1403
1406static struct target_type raid_target = { 1404static struct target_type raid_target = {
1407 .name = "raid", 1405 .name = "raid",
1408 .version = {1, 4, 1}, 1406 .version = {1, 4, 2},
1409 .module = THIS_MODULE, 1407 .module = THIS_MODULE,
1410 .ctr = raid_ctr, 1408 .ctr = raid_ctr,
1411 .dtr = raid_dtr, 1409 .dtr = raid_dtr,