summary refs log tree commit diff stats
path: root/target-s390x/misc_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-s390x/misc_helper.c')
-rw-r--r--target-s390x/misc_helper.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 71cbe34e05..462cfc85fc 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -232,10 +232,23 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
             program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
             return;
         }
-        iplb = g_malloc0(sizeof(struct IplParameterBlock));
-        cpu_physical_memory_read(addr, iplb, sizeof(struct IplParameterBlock));
+        iplb = g_malloc0(sizeof(IplParameterBlock));
+        cpu_physical_memory_read(addr, iplb, sizeof(iplb->len));
+        if (!iplb_valid_len(iplb)) {
+            env->regs[r1 + 1] = DIAG_308_RC_INVALID;
+            goto out;
+        }
+
+        cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len));
+
+        if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb)) {
+            env->regs[r1 + 1] = DIAG_308_RC_INVALID;
+            goto out;
+        }
+
         s390_ipl_update_diag308(iplb);
         env->regs[r1 + 1] = DIAG_308_RC_OK;
+out:
         g_free(iplb);
         return;
     case 6:
@@ -250,8 +263,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
         }
         iplb = s390_ipl_get_iplb();
         if (iplb) {
-            cpu_physical_memory_write(addr, iplb,
-                                      sizeof(struct IplParameterBlock));
+            cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len));
             env->regs[r1 + 1] = DIAG_308_RC_OK;
         } else {
             env->regs[r1 + 1] = DIAG_308_RC_NO_CONF;