diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2013-03-01 17:45:44 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2013-03-01 17:45:44 -0500 |
commit | fd7c092e711ebab55b2688d3859d95dfd0301f73 (patch) | |
tree | 3cc99f96f4a2de8e22347feb86b0ecd5dd7200d0 /drivers/md/dm-raid1.c | |
parent | 16245bdc9d3e22d1460341a655c8b5288953bc14 (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-raid1.c')
-rw-r--r-- | drivers/md/dm-raid1.c | 8 |
1 files changed, 3 insertions, 5 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index fa519185ebba..7f2419099b50 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -1347,8 +1347,8 @@ static char device_status_char(struct mirror *m) | |||
1347 | } | 1347 | } |
1348 | 1348 | ||
1349 | 1349 | ||
1350 | static int mirror_status(struct dm_target *ti, status_type_t type, | 1350 | static void mirror_status(struct dm_target *ti, status_type_t type, |
1351 | unsigned status_flags, char *result, unsigned maxlen) | 1351 | unsigned status_flags, char *result, unsigned maxlen) |
1352 | { | 1352 | { |
1353 | unsigned int m, sz = 0; | 1353 | unsigned int m, sz = 0; |
1354 | struct mirror_set *ms = (struct mirror_set *) ti->private; | 1354 | struct mirror_set *ms = (struct mirror_set *) ti->private; |
@@ -1383,8 +1383,6 @@ static int mirror_status(struct dm_target *ti, status_type_t type, | |||
1383 | if (ms->features & DM_RAID1_HANDLE_ERRORS) | 1383 | if (ms->features & DM_RAID1_HANDLE_ERRORS) |
1384 | DMEMIT(" 1 handle_errors"); | 1384 | DMEMIT(" 1 handle_errors"); |
1385 | } | 1385 | } |
1386 | |||
1387 | return 0; | ||
1388 | } | 1386 | } |
1389 | 1387 | ||
1390 | static int mirror_iterate_devices(struct dm_target *ti, | 1388 | static int mirror_iterate_devices(struct dm_target *ti, |
@@ -1403,7 +1401,7 @@ static int mirror_iterate_devices(struct dm_target *ti, | |||
1403 | 1401 | ||
1404 | static struct target_type mirror_target = { | 1402 | static struct target_type mirror_target = { |
1405 | .name = "mirror", | 1403 | .name = "mirror", |
1406 | .version = {1, 13, 1}, | 1404 | .version = {1, 13, 2}, |
1407 | .module = THIS_MODULE, | 1405 | .module = THIS_MODULE, |
1408 | .ctr = mirror_ctr, | 1406 | .ctr = mirror_ctr, |
1409 | .dtr = mirror_dtr, | 1407 | .dtr = mirror_dtr, |