diff options
| author | Mikulas Patocka <mpatocka@redhat.com> | 2013-03-01 22:45:44 +0000 | 
|---|---|---|
| committer | Alasdair G Kergon <agk@redhat.com> | 2013-03-01 22:45:44 +0000 | 
| commit | fd7c092e711ebab55b2688d3859d95dfd0301f73 (patch) | |
| tree | 3cc99f96f4a2de8e22347feb86b0ecd5dd7200d0 /drivers/md/dm-delay.c | |
| parent | 16245bdc9d3e22d1460341a655c8b5288953bc14 (diff) | |
| download | olio-linux-3.10-fd7c092e711ebab55b2688d3859d95dfd0301f73.tar.xz olio-linux-3.10-fd7c092e711ebab55b2688d3859d95dfd0301f73.zip  | |
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-delay.c')
| -rw-r--r-- | drivers/md/dm-delay.c | 8 | 
1 files changed, 3 insertions, 5 deletions
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index cc1bd048acb..c0d03b006e4 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c @@ -293,8 +293,8 @@ static int delay_map(struct dm_target *ti, struct bio *bio)  	return delay_bio(dc, dc->read_delay, bio);  } -static int delay_status(struct dm_target *ti, status_type_t type, -			unsigned status_flags, char *result, unsigned maxlen) +static void delay_status(struct dm_target *ti, status_type_t type, +			 unsigned status_flags, char *result, unsigned maxlen)  {  	struct delay_c *dc = ti->private;  	int sz = 0; @@ -314,8 +314,6 @@ static int delay_status(struct dm_target *ti, status_type_t type,  			       dc->write_delay);  		break;  	} - -	return 0;  }  static int delay_iterate_devices(struct dm_target *ti, @@ -337,7 +335,7 @@ out:  static struct target_type delay_target = {  	.name	     = "delay", -	.version     = {1, 2, 0}, +	.version     = {1, 2, 1},  	.module      = THIS_MODULE,  	.ctr	     = delay_ctr,  	.dtr	     = delay_dtr,  |