aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-snap.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-snap.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-snap.c')
-rw-r--r--drivers/md/dm-snap.c16
1 files changed, 6 insertions, 10 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 10079e07edf4..6e45e3774eab 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1836,8 +1836,8 @@ static void snapshot_merge_resume(struct dm_target *ti)
1836 start_merge(s); 1836 start_merge(s);
1837} 1837}
1838 1838
1839static int snapshot_status(struct dm_target *ti, status_type_t type, 1839static void snapshot_status(struct dm_target *ti, status_type_t type,
1840 unsigned status_flags, char *result, unsigned maxlen) 1840 unsigned status_flags, char *result, unsigned maxlen)
1841{ 1841{
1842 unsigned sz = 0; 1842 unsigned sz = 0;
1843 struct dm_snapshot *snap = ti->private; 1843 struct dm_snapshot *snap = ti->private;
@@ -1883,8 +1883,6 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
1883 maxlen - sz); 1883 maxlen - sz);
1884 break; 1884 break;
1885 } 1885 }
1886
1887 return 0;
1888} 1886}
1889 1887
1890static int snapshot_iterate_devices(struct dm_target *ti, 1888static int snapshot_iterate_devices(struct dm_target *ti,
@@ -2138,8 +2136,8 @@ static void origin_resume(struct dm_target *ti)
2138 ti->max_io_len = get_origin_minimum_chunksize(dev->bdev); 2136 ti->max_io_len = get_origin_minimum_chunksize(dev->bdev);
2139} 2137}
2140 2138
2141static int origin_status(struct dm_target *ti, status_type_t type, 2139static void origin_status(struct dm_target *ti, status_type_t type,
2142 unsigned status_flags, char *result, unsigned maxlen) 2140 unsigned status_flags, char *result, unsigned maxlen)
2143{ 2141{
2144 struct dm_dev *dev = ti->private; 2142 struct dm_dev *dev = ti->private;
2145 2143
@@ -2152,8 +2150,6 @@ static int origin_status(struct dm_target *ti, status_type_t type,
2152 snprintf(result, maxlen, "%s", dev->name); 2150 snprintf(result, maxlen, "%s", dev->name);
2153 break; 2151 break;
2154 } 2152 }
2155
2156 return 0;
2157} 2153}
2158 2154
2159static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, 2155static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
@@ -2180,7 +2176,7 @@ static int origin_iterate_devices(struct dm_target *ti,
2180 2176
2181static struct target_type origin_target = { 2177static struct target_type origin_target = {
2182 .name = "snapshot-origin", 2178 .name = "snapshot-origin",
2183 .version = {1, 8, 0}, 2179 .version = {1, 8, 1},
2184 .module = THIS_MODULE, 2180 .module = THIS_MODULE,
2185 .ctr = origin_ctr, 2181 .ctr = origin_ctr,
2186 .dtr = origin_dtr, 2182 .dtr = origin_dtr,
@@ -2193,7 +2189,7 @@ static struct target_type origin_target = {
2193 2189
2194static struct target_type snapshot_target = { 2190static struct target_type snapshot_target = {
2195 .name = "snapshot", 2191 .name = "snapshot",
2196 .version = {1, 11, 0}, 2192 .version = {1, 11, 1},
2197 .module = THIS_MODULE, 2193 .module = THIS_MODULE,
2198 .ctr = snapshot_ctr, 2194 .ctr = snapshot_ctr,
2199 .dtr = snapshot_dtr, 2195 .dtr = snapshot_dtr,