| 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) { |