[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v4 3/8] s390/sclp: rework sclp boundary and length checks
From: |
David Hildenbrand |
Subject: |
Re: [PATCH v4 3/8] s390/sclp: rework sclp boundary and length checks |
Date: |
Mon, 20 Jul 2020 10:17:54 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.9.0 |
On 24.06.20 22:23, Collin Walling wrote:
> Rework the SCLP boundary check to account for different SCLP commands
> (eventually) allowing different boundary sizes.
>
> Move the length check code into a separate function, and introduce a
> new function to determine the length of the read SCP data (i.e. the size
> from the start of the struct to where the CPU entries should begin).
>
> The format of read CPU info is unlikely to change in the future,
> so we do not require a separate function to calculate its length.
>
> Signed-off-by: Collin Walling <walling@linux.ibm.com>
> Acked-by: Janosch Frank <frankja@linux.ibm.com>
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> ---
> hw/s390x/sclp.c | 54 ++++++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 44 insertions(+), 10 deletions(-)
>
> diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
> index 181ce04007..5899c1e3b8 100644
> --- a/hw/s390x/sclp.c
> +++ b/hw/s390x/sclp.c
> @@ -49,6 +49,34 @@ static inline bool sclp_command_code_valid(uint32_t code)
> return false;
> }
>
> +static bool sccb_verify_boundary(uint64_t sccb_addr, uint32_t code,
> + SCCBHeader *header)
> +{
> + uint64_t sccb_max_addr = sccb_addr + be16_to_cpu(header->length) - 1;
> + uint64_t sccb_boundary = (sccb_addr & PAGE_MASK) + PAGE_SIZE;
> +
> + switch (code & SCLP_CMD_CODE_MASK) {
> + default:
> + if (sccb_max_addr < sccb_boundary) {
> + return true;
> + }
> + }
^ what is that?
if ((code & SCLP_CMD_CODE_MASK) && sccb_max_addr < sccb_boundary) {
return true;
}
> + header->response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
> + return false;
So we return "false" on success? At least I consider that weird when
returning the bool type. Maybe make it clearer what the function indicates
"sccb_boundary_is_invalid"
or leave it named as is and switch from return value "bool" to "int",
using "0" on success and "-EINVAL" on error.
> +}
> +
> +/* Calculates sufficient SCCB length to store a full Read SCP/CPU response */
> +static bool sccb_verify_length(SCCB *sccb, int num_cpus, int offset_cpu)
> +{
> + int required_len = offset_cpu + num_cpus * sizeof(CPUEntry);
> +
> + if (be16_to_cpu(sccb->h.length) < required_len) {
> + sccb->h.response_code =
> cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
> + return false;
> + }
> + return true;
> +}
> +
> static void prepare_cpu_entries(MachineState *ms, CPUEntry *entry, int
> *count)
> {
> uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
> @@ -66,6 +94,11 @@ static void prepare_cpu_entries(MachineState *ms, CPUEntry
> *entry, int *count)
> }
> }
>
> +static inline int get_read_scp_info_offset_cpu(void)
> +{
> + return offsetof(ReadInfo, entries);
> +}
> +
> /* Provide information about the configuration, CPUs and storage */
> static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
> {
> @@ -74,17 +107,16 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
> int cpu_count;
> int rnsize, rnmax;
> IplParameterBlock *ipib = s390_ipl_get_iplb();
> + int offset_cpu = get_read_scp_info_offset_cpu();
>
> - if (be16_to_cpu(sccb->h.length) <
> - (sizeof(ReadInfo) + machine->possible_cpus->len *
> sizeof(CPUEntry))) {
> - sccb->h.response_code =
> cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
> + if (!sccb_verify_length(sccb, machine->possible_cpus->len, offset_cpu)) {
> return;
> }
>
> /* CPU information */
> prepare_cpu_entries(machine, read_info->entries, &cpu_count);
> read_info->entries_cpu = cpu_to_be16(cpu_count);
> - read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
> + read_info->offset_cpu = cpu_to_be16(offset_cpu);
> read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
>
> read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
> @@ -133,17 +165,16 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB
> *sccb)
> {
> MachineState *machine = MACHINE(qdev_get_machine());
> ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
> + int offset_cpu = offsetof(ReadCpuInfo, entries);
> int cpu_count;
>
> - if (be16_to_cpu(sccb->h.length) <
> - (sizeof(ReadInfo) + machine->possible_cpus->len *
> sizeof(CPUEntry))) {
> - sccb->h.response_code =
> cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
> + if (!sccb_verify_length(sccb, machine->possible_cpus->len, offset_cpu)) {
> return;
> }
>
> prepare_cpu_entries(machine, cpu_info->entries, &cpu_count);
> cpu_info->nr_configured = cpu_to_be16(cpu_count);
> - cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo,
> entries));
> + cpu_info->offset_configured = cpu_to_be16(offset_cpu);
> cpu_info->nr_standby = cpu_to_be16(0);
>
> /* The standby offset is 16-byte for each CPU */
> @@ -229,6 +260,10 @@ int sclp_service_call_protected(CPUS390XState *env,
> uint64_t sccb,
> goto out_write;
> }
>
> + if (!sccb_verify_boundary(sccb, code, &work_sccb.h)) {
> + goto out_write;
> + }
> +
> sclp_c->execute(sclp, &work_sccb, code);
> out_write:
> s390_cpu_pv_mem_write(env_archcpu(env), 0, &work_sccb,
> @@ -274,8 +309,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb,
> uint32_t code)
> goto out_write;
> }
>
> - if ((sccb + be16_to_cpu(work_sccb.h.length)) > ((sccb & PAGE_MASK) +
> PAGE_SIZE)) {
> - work_sccb.h.response_code =
> cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
> + if (!sccb_verify_boundary(sccb, code, &work_sccb.h)) {
> goto out_write;
> }
>
>
--
Thanks,
David / dhildenb
- Re: [PATCH v4 3/8] s390/sclp: rework sclp boundary and length checks,
David Hildenbrand <=