lkml.org 
[lkml]   [2013]   [Nov]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[ 27/32] dm snapshot: fix data corruption
    Date
    3.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Mikulas Patocka <mpatocka@redhat.com>

    commit e9c6a182649f4259db704ae15a91ac820e63b0ca upstream.

    This patch fixes a particular type of data corruption that has been
    encountered when loading a snapshot's metadata from disk.

    When we allocate a new chunk in persistent_prepare, we increment
    ps->next_free and we make sure that it doesn't point to a metadata area
    by further incrementing it if necessary.

    When we load metadata from disk on device activation, ps->next_free is
    positioned after the last used data chunk. However, if this last used
    data chunk is followed by a metadata area, ps->next_free is positioned
    erroneously to the metadata area. A newly-allocated chunk is placed at
    the same location as the metadata area, resulting in data or metadata
    corruption.

    This patch changes the code so that ps->next_free skips the metadata
    area when metadata are loaded in function read_exceptions.

    The patch also moves a piece of code from persistent_prepare_exception
    to a separate function skip_metadata to avoid code duplication.

    CVE-2013-4299

    Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
    Cc: Mike Snitzer <snitzer@redhat.com>
    Signed-off-by: Alasdair G Kergon <agk@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/md/dm-snap-persistent.c | 18 ++++++++++++------
    1 file changed, 12 insertions(+), 6 deletions(-)

    --- a/drivers/md/dm-snap-persistent.c
    +++ b/drivers/md/dm-snap-persistent.c
    @@ -269,6 +269,14 @@ static chunk_t area_location(struct psto
    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
    * chunk which holds the header.
    @@ -502,6 +510,8 @@ static int read_exceptions(struct pstore

    ps->current_area--;

    + skip_metadata(ps);
    +
    return 0;
    }

    @@ -616,8 +626,6 @@ static int persistent_prepare_exception(
    struct dm_exception *e)
    {
    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);

    /* Is there enough room ? */
    @@ -630,10 +638,8 @@ static int persistent_prepare_exception(
    * Move onto the next free pending, making sure to take
    * into account the location of the metadata chunks.
    */
    - stride = (ps->exceptions_per_area + 1);
    - next_free = ++ps->next_free;
    - if (sector_div(next_free, stride) == 1)
    - ps->next_free++;
    + ps->next_free++;
    + skip_metadata(ps);

    atomic_inc(&ps->pending_count);
    return 0;



    \
     
     \ /
      Last update: 2013-11-01 23:21    [W:4.124 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site