Commit 8359ffa5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dm-3.12-fix-cve' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device-mapper fix from Alasdair Kergon:
 "A patch to avoid data corruption in a device-mapper snapshot.

  This is primarily a data corruption bug that all users of
  device-mapper snapshots will want to fix.  The CVE is due to a data
  leak under specific circumstances if, for example, the snapshot is
  presented to a virtual machine: a block written as data inside the VM
  can get interpreted incorrectly on the host outside the VM as
  metadata, causing the host to provide the VM with access to blocks it
  would not otherwise see.  This is likely to affect few, if any,
  people"

* tag 'dm-3.12-fix-cve' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm snapshot: fix data corruption
parents 386aa051 e9c6a182
...@@ -269,6 +269,14 @@ static chunk_t area_location(struct pstore *ps, chunk_t area) ...@@ -269,6 +269,14 @@ static chunk_t area_location(struct pstore *ps, chunk_t area)
return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area); return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area);
} }
static void skip_metadata(struct pstore *ps)
{
uint32_t stride = ps->exceptions_per_area + 1;
chunk_t next_free = ps->next_free;
if (sector_div(next_free, stride) == NUM_SNAPSHOT_HDR_CHUNKS)
ps->next_free++;
}
/* /*
* Read or write a metadata area. Remembering to skip the first * Read or write a metadata area. Remembering to skip the first
* chunk which holds the header. * chunk which holds the header.
...@@ -502,6 +510,8 @@ static int read_exceptions(struct pstore *ps, ...@@ -502,6 +510,8 @@ static int read_exceptions(struct pstore *ps,
ps->current_area--; ps->current_area--;
skip_metadata(ps);
return 0; return 0;
} }
...@@ -616,8 +626,6 @@ static int persistent_prepare_exception(struct dm_exception_store *store, ...@@ -616,8 +626,6 @@ static int persistent_prepare_exception(struct dm_exception_store *store,
struct dm_exception *e) struct dm_exception *e)
{ {
struct pstore *ps = get_info(store); struct pstore *ps = get_info(store);
uint32_t stride;
chunk_t next_free;
sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev); sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
/* Is there enough room ? */ /* Is there enough room ? */
...@@ -630,10 +638,8 @@ static int persistent_prepare_exception(struct dm_exception_store *store, ...@@ -630,10 +638,8 @@ static int persistent_prepare_exception(struct dm_exception_store *store,
* Move onto the next free pending, making sure to take * Move onto the next free pending, making sure to take
* into account the location of the metadata chunks. * into account the location of the metadata chunks.
*/ */
stride = (ps->exceptions_per_area + 1); ps->next_free++;
next_free = ++ps->next_free; skip_metadata(ps);
if (sector_div(next_free, stride) == 1)
ps->next_free++;
atomic_inc(&ps->pending_count); atomic_inc(&ps->pending_count);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment