From: Greg Kroah-Hartman Date: Thu, 31 Aug 2017 06:20:32 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v3.18.69~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=12a1c109838d33ce644b184beb7a2c42bda9966a;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: arm64-fpsimd-prevent-registers-leaking-across-exec.patch scsi-sg-protect-accesses-to-reserved-page-array.patch scsi-sg-reset-res_in_use-after-unlinking-reserved-array.patch --- diff --git a/queue-4.4/arm64-fpsimd-prevent-registers-leaking-across-exec.patch b/queue-4.4/arm64-fpsimd-prevent-registers-leaking-across-exec.patch new file mode 100644 index 00000000000..e115d8a138b --- /dev/null +++ b/queue-4.4/arm64-fpsimd-prevent-registers-leaking-across-exec.patch @@ -0,0 +1,54 @@ +From 096622104e14d8a1db4860bd557717067a0515d2 Mon Sep 17 00:00:00 2001 +From: Dave Martin +Date: Fri, 18 Aug 2017 16:57:01 +0100 +Subject: arm64: fpsimd: Prevent registers leaking across exec + +From: Dave Martin + +commit 096622104e14d8a1db4860bd557717067a0515d2 upstream. + +There are some tricky dependencies between the different stages of +flushing the FPSIMD register state during exec, and these can race +with context switch in ways that can cause the old task's regs to +leak across. In particular, a context switch during the memset() can +cause some of the task's old FPSIMD registers to reappear. + +Disabling preemption for this small window would be no big deal for +performance: preemption is already disabled for similar scenarios +like updating the FPSIMD registers in sigreturn. + +So, instead of rearranging things in ways that might swap existing +subtle bugs for new ones, this patch just disables preemption +around the FPSIMD state flushing so that races of this type can't +occur here. This brings fpsimd_flush_thread() into line with other +code paths. + +Fixes: 674c242c9323 ("arm64: flush FP/SIMD state correctly after execve()") +Reviewed-by: Ard Biesheuvel +Signed-off-by: Dave Martin +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + +For stable only. + +3.17.x-4.0.x don't appear active, and this patch isn't sufficient to fix +them (they would need 674c242c9323 also). + + arch/arm64/kernel/fpsimd.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -157,9 +157,11 @@ void fpsimd_thread_switch(struct task_st + + void fpsimd_flush_thread(void) + { ++ preempt_disable(); + memset(¤t->thread.fpsimd_state, 0, sizeof(struct fpsimd_state)); + fpsimd_flush_task_state(current); + set_thread_flag(TIF_FOREIGN_FPSTATE); ++ preempt_enable(); + } + + /* diff --git a/queue-4.4/scsi-sg-protect-accesses-to-reserved-page-array.patch b/queue-4.4/scsi-sg-protect-accesses-to-reserved-page-array.patch new file mode 100644 index 00000000000..ec4f46daadb --- /dev/null +++ b/queue-4.4/scsi-sg-protect-accesses-to-reserved-page-array.patch @@ -0,0 +1,172 @@ +From 1bc0eb0446158cc76562176b80623aa119afee5b Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 7 Apr 2017 09:34:14 +0200 +Subject: scsi: sg: protect accesses to 'reserved' page array + +From: Hannes Reinecke + +commit 1bc0eb0446158cc76562176b80623aa119afee5b upstream. + +The 'reserved' page array is used as a short-cut for mapping data, +saving us to allocate pages per request. However, the 'reserved' array +is only capable of holding one request, so this patch introduces a mutex +for protect 'sg_fd' against concurrent accesses. + +Signed-off-by: Hannes Reinecke +Reviewed-by: Johannes Thumshirn +Tested-by: Johannes Thumshirn +Reviewed-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +[toddpoynor@google.com: backport to 3.18-4.9, fixup for bad ioctl +SG_SET_FORCE_LOW_DMA code removed in later versions and not modified by +the original patch.] + +Signed-off-by: Hannes Reinecke +Reviewed-by: Johannes Thumshirn +Tested-by: Johannes Thumshirn +Reviewed-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Signed-off-by: Todd Poynor +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/sg.c | 47 ++++++++++++++++++++++++++--------------------- + 1 file changed, 26 insertions(+), 21 deletions(-) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -153,6 +153,7 @@ typedef struct sg_fd { /* holds the sta + struct sg_device *parentdp; /* owning device */ + wait_queue_head_t read_wait; /* queue read until command done */ + rwlock_t rq_list_lock; /* protect access to list in req_arr */ ++ struct mutex f_mutex; /* protect against changes in this fd */ + int timeout; /* defaults to SG_DEFAULT_TIMEOUT */ + int timeout_user; /* defaults to SG_DEFAULT_TIMEOUT_USER */ + Sg_scatter_hold reserve; /* buffer held for this file descriptor */ +@@ -166,6 +167,7 @@ typedef struct sg_fd { /* holds the sta + unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */ + char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ + char mmap_called; /* 0 -> mmap() never called on this fd */ ++ char res_in_use; /* 1 -> 'reserve' array in use */ + struct kref f_ref; + struct execute_work ew; + } Sg_fd; +@@ -209,7 +211,6 @@ static void sg_remove_sfp(struct kref *) + static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); + static Sg_request *sg_add_request(Sg_fd * sfp); + static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); +-static int sg_res_in_use(Sg_fd * sfp); + static Sg_device *sg_get_dev(int dev); + static void sg_device_destroy(struct kref *kref); + +@@ -625,6 +626,7 @@ sg_write(struct file *filp, const char _ + } + buf += SZ_SG_HEADER; + __get_user(opcode, buf); ++ mutex_lock(&sfp->f_mutex); + if (sfp->next_cmd_len > 0) { + cmd_size = sfp->next_cmd_len; + sfp->next_cmd_len = 0; /* reset so only this write() effected */ +@@ -633,6 +635,7 @@ sg_write(struct file *filp, const char _ + if ((opcode >= 0xc0) && old_hdr.twelve_byte) + cmd_size = 12; + } ++ mutex_unlock(&sfp->f_mutex); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp, + "sg_write: scsi opcode=0x%02x, cmd_size=%d\n", (int) opcode, cmd_size)); + /* Determine buffer size. */ +@@ -732,7 +735,7 @@ sg_new_write(Sg_fd *sfp, struct file *fi + sg_remove_request(sfp, srp); + return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */ + } +- if (sg_res_in_use(sfp)) { ++ if (sfp->res_in_use) { + sg_remove_request(sfp, srp); + return -EBUSY; /* reserve buffer already being used */ + } +@@ -902,7 +905,7 @@ sg_ioctl(struct file *filp, unsigned int + return result; + if (val) { + sfp->low_dma = 1; +- if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) { ++ if ((0 == sfp->low_dma) && !sfp->res_in_use) { + val = (int) sfp->reserve.bufflen; + sg_remove_scat(sfp, &sfp->reserve); + sg_build_reserve(sfp, val); +@@ -977,12 +980,18 @@ sg_ioctl(struct file *filp, unsigned int + return -EINVAL; + val = min_t(int, val, + max_sectors_bytes(sdp->device->request_queue)); ++ mutex_lock(&sfp->f_mutex); + if (val != sfp->reserve.bufflen) { +- if (sg_res_in_use(sfp) || sfp->mmap_called) ++ if (sfp->mmap_called || ++ sfp->res_in_use) { ++ mutex_unlock(&sfp->f_mutex); + return -EBUSY; ++ } ++ + sg_remove_scat(sfp, &sfp->reserve); + sg_build_reserve(sfp, val); + } ++ mutex_unlock(&sfp->f_mutex); + return 0; + case SG_GET_RESERVED_SIZE: + val = min_t(int, sfp->reserve.bufflen, +@@ -1737,13 +1746,22 @@ sg_start_req(Sg_request *srp, unsigned c + md = &map_data; + + if (md) { +- if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen) ++ mutex_lock(&sfp->f_mutex); ++ if (dxfer_len <= rsv_schp->bufflen && ++ !sfp->res_in_use) { ++ sfp->res_in_use = 1; + sg_link_reserve(sfp, srp, dxfer_len); +- else { ++ } else if ((hp->flags & SG_FLAG_MMAP_IO) && sfp->res_in_use) { ++ mutex_unlock(&sfp->f_mutex); ++ return -EBUSY; ++ } else { + res = sg_build_indirect(req_schp, sfp, dxfer_len); +- if (res) ++ if (res) { ++ mutex_unlock(&sfp->f_mutex); + return res; ++ } + } ++ mutex_unlock(&sfp->f_mutex); + + md->pages = req_schp->pages; + md->page_order = req_schp->page_order; +@@ -2145,6 +2163,7 @@ sg_add_sfp(Sg_device * sdp) + rwlock_init(&sfp->rq_list_lock); + + kref_init(&sfp->f_ref); ++ mutex_init(&sfp->f_mutex); + sfp->timeout = SG_DEFAULT_TIMEOUT; + sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER; + sfp->force_packid = SG_DEF_FORCE_PACK_ID; +@@ -2220,20 +2239,6 @@ sg_remove_sfp(struct kref *kref) + schedule_work(&sfp->ew.work); + } + +-static int +-sg_res_in_use(Sg_fd * sfp) +-{ +- const Sg_request *srp; +- unsigned long iflags; +- +- read_lock_irqsave(&sfp->rq_list_lock, iflags); +- for (srp = sfp->headrp; srp; srp = srp->nextrp) +- if (srp->res_used) +- break; +- read_unlock_irqrestore(&sfp->rq_list_lock, iflags); +- return srp ? 1 : 0; +-} +- + #ifdef CONFIG_SCSI_PROC_FS + static int + sg_idr_max_id(int id, void *p, void *data) diff --git a/queue-4.4/scsi-sg-reset-res_in_use-after-unlinking-reserved-array.patch b/queue-4.4/scsi-sg-reset-res_in_use-after-unlinking-reserved-array.patch new file mode 100644 index 00000000000..70e39cdef18 --- /dev/null +++ b/queue-4.4/scsi-sg-reset-res_in_use-after-unlinking-reserved-array.patch @@ -0,0 +1,38 @@ +From e791ce27c3f6a1d3c746fd6a8f8e36c9540ec6f9 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Mon, 24 Apr 2017 10:26:36 +0200 +Subject: scsi: sg: reset 'res_in_use' after unlinking reserved array + +From: Hannes Reinecke + +commit e791ce27c3f6a1d3c746fd6a8f8e36c9540ec6f9 upstream. + +Once the reserved page array is unused we can reset the 'res_in_use' +state; here we can do a lazy update without holding the mutex as we only +need to check against concurrent access, not concurrent release. + +[mkp: checkpatch] + +Fixes: 1bc0eb044615 ("scsi: sg: protect accesses to 'reserved' page array") +Signed-off-by: Hannes Reinecke +Reviewed-by: Johannes Thumshirn +Reviewed-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Cc: Todd Poynor +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/sg.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -2052,6 +2052,8 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_reques + req_schp->sglist_len = 0; + sfp->save_scat_len = 0; + srp->res_used = 0; ++ /* Called without mutex lock to avoid deadlock */ ++ sfp->res_in_use = 0; + } + + static Sg_request * diff --git a/queue-4.4/series b/queue-4.4/series index fe943ee44b6..37fd9d2e60f 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -9,3 +9,6 @@ p54-memset-0-whole-array.patch lpfc-fix-device-discovery-failures-during-switch-reboot-test.patch arm64-mm-abort-uaccess-retries-upon-fatal-signal.patch x86-io-add-memory-clobber-to-insb-insw-insl-outsb-outsw-outsl.patch +arm64-fpsimd-prevent-registers-leaking-across-exec.patch +scsi-sg-protect-accesses-to-reserved-page-array.patch +scsi-sg-reset-res_in_use-after-unlinking-reserved-array.patch