diff options
author | 2013-08-24 11:33:21 -0700 | |
---|---|---|
committer | 2013-08-24 11:33:21 -0700 | |
commit | 5befb98b30cce19bdf2221ea48c39f1fec5c4568 (patch) | |
tree | 5a16eb1dfac34661b6529a26e2486cb1abe21e37 /fs | |
parent | ARC: [lib] strchr breakage in Big-endian configuration (diff) | |
parent | [SCSI] zfcp: remove access control tables interface (keep sysfs files) (diff) | |
download | linux-5befb98b30cce19bdf2221ea48c39f1fec5c4568.tar.gz linux-5befb98b30cce19bdf2221ea48c39f1fec5c4568.tar.bz2 linux-5befb98b30cce19bdf2221ea48c39f1fec5c4568.zip |
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley:
"This is a set of small bug fixes for lpfc and zfcp and a fix for a
fairly nasty bug in sg where a process which cancels I/O completes in
a kernel thread which would then try to write back to the now gone
userspace and end up writing to a random kernel address instead"
* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
[SCSI] zfcp: remove access control tables interface (keep sysfs files)
[SCSI] zfcp: fix schedule-inside-lock in scsi_device list loops
[SCSI] zfcp: fix lock imbalance by reworking request queue locking
[SCSI] sg: Fix user memory corruption when SG_IO is interrupted by a signal
[SCSI] lpfc: Don't force CONFIG_GENERIC_CSUM on
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bio.c | 20 |
1 files changed, 15 insertions, 5 deletions
@@ -1045,12 +1045,22 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, int bio_uncopy_user(struct bio *bio) { struct bio_map_data *bmd = bio->bi_private; - int ret = 0; + struct bio_vec *bvec; + int ret = 0, i; - if (!bio_flagged(bio, BIO_NULL_MAPPED)) - ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, - bmd->nr_sgvecs, bio_data_dir(bio) == READ, - 0, bmd->is_our_pages); + if (!bio_flagged(bio, BIO_NULL_MAPPED)) { + /* + * if we're in a workqueue, the request is orphaned, so + * don't copy into a random user address space, just free. + */ + if (current->mm) + ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, + bmd->nr_sgvecs, bio_data_dir(bio) == READ, + 0, bmd->is_our_pages); + else if (bmd->is_our_pages) + bio_for_each_segment_all(bvec, bio, i) + __free_page(bvec->bv_page); + } bio_free_map_data(bmd); bio_put(bio); return ret; |