Skip to content

Commit

Permalink
loop: zero fill bio instead of return -EIO for partial read
Browse files Browse the repository at this point in the history
commit 8268f5a ("deny partial write for loop dev fd") tried to fix the
loop device partial read information leak problem.  But it changed the
semantics of read behavior.  When we read beyond the end of the device we
should get 0 bytes, which is normal behavior, we should not just return
-EIO

Instead of returning -EIO, zero out the bio to avoid information leak in
case of partail read.

Signed-off-by: Dave Young <dyoung@redhat.com>
Reviewed-by: Jeff Moyer <jmoyer@redhat.com>
Tested-by: Jeff Moyer <jmoyer@redhat.com>
Cc: Dmitry Monakhov <dmonakhov@sw.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Dave Young authored and Jens Axboe committed Feb 8, 2012
1 parent 5abebfd commit 306df07
Showing 1 changed file with 13 additions and 11 deletions.
24 changes: 13 additions & 11 deletions drivers/block/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,14 +356,14 @@ lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
return __splice_from_pipe(pipe, sd, lo_splice_actor);
}

static int
static ssize_t
do_lo_receive(struct loop_device *lo,
struct bio_vec *bvec, int bsize, loff_t pos)
{
struct lo_read_data cookie;
struct splice_desc sd;
struct file *file;
long retval;
ssize_t retval;

cookie.lo = lo;
cookie.page = bvec->bv_page;
Expand All @@ -379,26 +379,28 @@ do_lo_receive(struct loop_device *lo,
file = lo->lo_backing_file;
retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);

if (retval < 0)
return retval;
if (retval != bvec->bv_len)
return -EIO;
return 0;
return retval;
}

static int
lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
{
struct bio_vec *bvec;
int i, ret = 0;
ssize_t s;
int i;

bio_for_each_segment(bvec, bio, i) {
ret = do_lo_receive(lo, bvec, bsize, pos);
if (ret < 0)
s = do_lo_receive(lo, bvec, bsize, pos);
if (s < 0)
return s;

if (s != bvec->bv_len) {
zero_fill_bio(bio);
break;
}
pos += bvec->bv_len;
}
return ret;
return 0;
}

static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
Expand Down

0 comments on commit 306df07

Please sign in to comment.