diff options
Diffstat (limited to 'queue-3.16/scsi-sg-recheck-mmap_io-request-length-with-lock-held.patch')
-rw-r--r-- | queue-3.16/scsi-sg-recheck-mmap_io-request-length-with-lock-held.patch | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/queue-3.16/scsi-sg-recheck-mmap_io-request-length-with-lock-held.patch b/queue-3.16/scsi-sg-recheck-mmap_io-request-length-with-lock-held.patch new file mode 100644 index 00000000..d40b3a94 --- /dev/null +++ b/queue-3.16/scsi-sg-recheck-mmap_io-request-length-with-lock-held.patch @@ -0,0 +1,45 @@ +From: Todd Poynor <toddpoynor@google.com> +Date: Tue, 15 Aug 2017 21:48:43 -0700 +Subject: scsi: sg: recheck MMAP_IO request length with lock held + +commit 8d26f491116feaa0b16de370b6a7ba40a40fa0b4 upstream. + +Commit 1bc0eb044615 ("scsi: sg: protect accesses to 'reserved' page +array") adds needed concurrency protection for the "reserve" buffer. +Some checks that are initially made outside the lock are replicated once +the lock is taken to ensure the checks and resulting decisions are made +using consistent state. + +The check that a request with flag SG_FLAG_MMAP_IO set fits in the +reserve buffer also needs to be performed again under the lock to ensure +the reserve buffer length compared against matches the value in effect +when the request is linked to the reserve buffer. An -ENOMEM should be +returned in this case, instead of switching over to an indirect buffer +as for non-MMAP_IO requests. + +Signed-off-by: Todd Poynor <toddpoynor@google.com> +Acked-by: Douglas Gilbert <dgilbert@interlog.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/scsi/sg.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -1772,9 +1772,12 @@ sg_start_req(Sg_request *srp, unsigned c + !sfp->res_in_use) { + sfp->res_in_use = 1; + sg_link_reserve(sfp, srp, dxfer_len); +- } else if ((hp->flags & SG_FLAG_MMAP_IO) && sfp->res_in_use) { ++ } else if (hp->flags & SG_FLAG_MMAP_IO) { ++ res = -EBUSY; /* sfp->res_in_use == 1 */ ++ if (dxfer_len > rsv_schp->bufflen) ++ res = -ENOMEM; + mutex_unlock(&sfp->f_mutex); +- return -EBUSY; ++ return res; + } else { + res = sg_build_indirect(req_schp, sfp, dxfer_len); + if (res) { |