Commit 306df071 authored by Dave Young's avatar Dave Young Committed by Jens Axboe

loop: zero fill bio instead of return -EIO for partial read

commit 8268f5a7 ("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: default avatarDave Young <dyoung@redhat.com>
Reviewed-by: default avatarJeff Moyer <jmoyer@redhat.com>
Tested-by: default avatarJeff Moyer <jmoyer@redhat.com>
Cc: Dmitry Monakhov <dmonakhov@sw.ru>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 5abebfdd
...@@ -356,14 +356,14 @@ lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd) ...@@ -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); return __splice_from_pipe(pipe, sd, lo_splice_actor);
} }
static int static ssize_t
do_lo_receive(struct loop_device *lo, do_lo_receive(struct loop_device *lo,
struct bio_vec *bvec, int bsize, loff_t pos) struct bio_vec *bvec, int bsize, loff_t pos)
{ {
struct lo_read_data cookie; struct lo_read_data cookie;
struct splice_desc sd; struct splice_desc sd;
struct file *file; struct file *file;
long retval; ssize_t retval;
cookie.lo = lo; cookie.lo = lo;
cookie.page = bvec->bv_page; cookie.page = bvec->bv_page;
...@@ -379,26 +379,28 @@ do_lo_receive(struct loop_device *lo, ...@@ -379,26 +379,28 @@ do_lo_receive(struct loop_device *lo,
file = lo->lo_backing_file; file = lo->lo_backing_file;
retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor); retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
if (retval < 0) return retval;
return retval;
if (retval != bvec->bv_len)
return -EIO;
return 0;
} }
static int static int
lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos) lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
{ {
struct bio_vec *bvec; struct bio_vec *bvec;
int i, ret = 0; ssize_t s;
int i;
bio_for_each_segment(bvec, bio, i) { bio_for_each_segment(bvec, bio, i) {
ret = do_lo_receive(lo, bvec, bsize, pos); s = do_lo_receive(lo, bvec, bsize, pos);
if (ret < 0) if (s < 0)
return s;
if (s != bvec->bv_len) {
zero_fill_bio(bio);
break; break;
}
pos += bvec->bv_len; pos += bvec->bv_len;
} }
return ret; return 0;
} }
static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
......
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