]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
s390/dasd: Fix invalid dereferencing of indirect CCW data pointer
authorStefan Haberland <sth@linux.ibm.com>
Wed, 3 Jul 2024 09:23:12 +0000 (11:23 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 Jul 2024 10:51:19 +0000 (12:51 +0200)
commit b3a58f3b90f564f42a5c35778d8c5107b2c2150b upstream.

Fix invalid dereferencing of indirect CCW data pointer in
dasd_eckd_dump_sense() that leads to a kernel panic in error cases.

When using indirect addressing for DASD CCWs (IDAW) the CCW CDA pointer
does not contain the data address itself but a pointer to the IDAL.
This needs to be translated from physical to virtual as well before
using it.

This dereferencing is also used for dasd_page_cache and also fixed
although it is very unlikely that this code path ever gets used.

Fixes: c0bd39601c13 ("s390/dasd: use new address translation helpers")
Cc: stable@vger.kernel.org
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c

index 180a008d38eaaffbea289e26540d4a38f6f0fb0e..4118b64781cb5198e02d56274dcff00934f046d2 100644 (file)
@@ -4906,7 +4906,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
                                ccw++;
                        if (dst) {
                                if (ccw->flags & CCW_FLAG_IDA)
-                                       cda = *((char **)dma32_to_virt(ccw->cda));
+                                       cda = dma64_to_virt(*((dma64_t *)dma32_to_virt(ccw->cda)));
                                else
                                        cda = dma32_to_virt(ccw->cda);
                                if (dst != cda) {
@@ -5525,7 +5525,7 @@ dasd_eckd_dump_ccw_range(struct dasd_device *device, struct ccw1 *from,
 
                /* get pointer to data (consider IDALs) */
                if (from->flags & CCW_FLAG_IDA)
-                       datap = (char *)*((addr_t *)dma32_to_virt(from->cda));
+                       datap = dma64_to_virt(*((dma64_t *)dma32_to_virt(from->cda)));
                else
                        datap = dma32_to_virt(from->cda);
 
index 361e9bd752570523372792d915187d8374bce9aa..9f2023a077c202365d7a4405885ba1d6223f79a8 100644 (file)
@@ -585,7 +585,7 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req)
                                ccw++;
                        if (dst) {
                                if (ccw->flags & CCW_FLAG_IDA)
-                                       cda = *((char **)dma32_to_virt(ccw->cda));
+                                       cda = dma64_to_virt(*((dma64_t *)dma32_to_virt(ccw->cda)));
                                else
                                        cda = dma32_to_virt(ccw->cda);
                                if (dst != cda) {