Skip to content

Commit 9d2ea97

Browse files
Pádraig Bradyttx
Pádraig Brady
authored andcommitted
Don't leak info from libvirt LVM backed instances
* nova/virt/libvirt/utils.py (remove_logical_volumes): Overwrite each logical volume with zero (clear_logical_volume): LV obfuscation implementation. (logical_volume_size): A utility function used by clear_logical_volume() Fixes bug: 1070539 Change-Id: I4e1024de8dfe9b0be3b0d6437c836d2042862f85
1 parent ec6550f commit 9d2ea97

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

Diff for: nova/virt/libvirt/utils.py

+47
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,55 @@ def logical_volume_info(path):
172172
return dict(zip(*info))
173173

174174

175+
def logical_volume_size(path):
176+
"""Get logical volume size in bytes.
177+
178+
:param path: logical volume path
179+
"""
180+
# TODO(p-draigbrady) POssibly replace with the more general
181+
# use of blockdev --getsize64 in future
182+
out, _err = execute('lvs', '-o', 'lv_size', '--noheadings', '--units',
183+
'b', '--nosuffix', path, run_as_root=True)
184+
185+
return int(out)
186+
187+
188+
def clear_logical_volume(path):
189+
"""Obfuscate the logical volume.
190+
191+
:param path: logical volume path
192+
"""
193+
# TODO(p-draigbrady): We currently overwrite with zeros
194+
# but we may want to make this configurable in future
195+
# for more or less security conscious setups.
196+
197+
vol_size = logical_volume_size(path)
198+
bs = 1024 * 1024
199+
direct_flags = ('oflag=direct',)
200+
remaining_bytes = vol_size
201+
202+
# The loop caters for versions of dd that
203+
# don't support the iflag=count_bytes option.
204+
while remaining_bytes:
205+
zero_blocks = remaining_bytes / bs
206+
seek_blocks = (vol_size - remaining_bytes) / bs
207+
zero_cmd = ('dd', 'bs=%s' % bs,
208+
'if=/dev/zero', 'of=%s' % path,
209+
'seek=%s' % seek_blocks, 'count=%s' % zero_blocks)
210+
zero_cmd += direct_flags
211+
if zero_blocks:
212+
utils.execute(*zero_cmd, run_as_root=True)
213+
remaining_bytes %= bs
214+
bs /= 1024 # Limit to 3 iterations
215+
direct_flags = () # Only use O_DIRECT with initial block size
216+
217+
175218
def remove_logical_volumes(*paths):
176219
"""Remove one or more logical volume."""
220+
221+
for path in paths:
222+
clear_logical_volume(path)
223+
177224
if paths:
178225
lvremove = ('lvremove', '-f') + paths
179226
execute(*lvremove, attempts=3, run_as_root=True)

0 commit comments

Comments
 (0)