[bug report] ACPI: APEI: EINJ: Discover EINJv2 parameters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Zaid Alali,

Commit 691a0f0a557b ("ACPI: APEI: EINJ: Discover EINJv2 parameters")
from Jun 17, 2025 (linux-next), leads to the following Smatch static
checker warning:

	drivers/acpi/apei/einj-core.c:331 einj_get_parameter_address()
	warn: using integer overflow function 'size_add()' for math

drivers/acpi/apei/einj-core.c
    286 static void __iomem *einj_get_parameter_address(void)
    287 {
    288         int i;
    289         u64 pa_v4 = 0, pa_v5 = 0;
    290         struct acpi_whea_header *entry;
    291 
    292         entry = EINJ_TAB_ENTRY(einj_tab);
    293         for (i = 0; i < einj_tab->entries; i++) {
    294                 if (entry->action == ACPI_EINJ_SET_ERROR_TYPE &&
    295                     entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
    296                     entry->register_region.space_id ==
    297                     ACPI_ADR_SPACE_SYSTEM_MEMORY)
    298                         pa_v4 = get_unaligned(&entry->register_region.address);
    299                 if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS &&
    300                     entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
    301                     entry->register_region.space_id ==
    302                     ACPI_ADR_SPACE_SYSTEM_MEMORY)
    303                         pa_v5 = get_unaligned(&entry->register_region.address);
    304                 entry++;
    305         }
    306         if (pa_v5) {
    307                 struct set_error_type_with_address v5param;
    308                 struct set_error_type_with_address __iomem *p;
    309 
    310                 v5param_size = sizeof(v5param);
    311                 p = acpi_os_map_iomem(pa_v5, sizeof(*p));
    312                 if (p) {
    313                         int offset, len;
    314 
    315                         memcpy_fromio(&v5param, p, v5param_size);
    316                         acpi5 = 1;
    317                         check_vendor_extension(pa_v5, &v5param);
    318                         if (available_error_type & ACPI65_EINJV2_SUPP) {
    319                                 len = v5param.einjv2_struct.length;

My guess is that in real life all these values have to be correct.

    320                                 offset = offsetof(struct einjv2_extension_struct, component_arr);
    321                                 max_nr_components = (len - offset) /

Like you couldn't pass a negative len and expect this to boot etc...

    322                                                 sizeof(v5param.einjv2_struct.component_arr[0]);
    323                                 /*
    324                                  * The first call to acpi_os_map_iomem above does not include the
    325                                  * component array, instead it is used to read and calculate maximum
    326                                  * number of components supported by the system. Below, the mapping
    327                                  * is expanded to include the component array.
    328                                  */
    329                                 acpi_os_unmap_iomem(p, v5param_size);
    330                                 offset = offsetof(struct set_error_type_with_address, einjv2_struct);
--> 331                                 v5param_size = offset + struct_size(&v5param.einjv2_struct,

So the struct_size() here is probably just used for readability and not
for kernel hardening.  So the "offset + " is probably fine and doesn't
need to be changed to size_add(offset, struct_size());

    332                                         component_arr, max_nr_components);
    333                                 p = acpi_os_map_iomem(pa_v5, v5param_size);
    334                         }
    335                         return p;
    336                 }
    337         }
    338         if (param_extension && pa_v4) {
    339                 struct einj_parameter v4param;
    340                 struct einj_parameter __iomem *p;
    341 
    342                 p = acpi_os_map_iomem(pa_v4, sizeof(*p));
    343                 if (!p)
    344                         return NULL;
    345                 memcpy_fromio(&v4param, p, sizeof(v4param));
    346                 if (v4param.reserved1 || v4param.reserved2) {
    347                         acpi_os_unmap_iomem(p, sizeof(v4param));
    348                         return NULL;
    349                 }
    350                 return p;
    351         }
    352 
    353         return NULL;
    354 }

regards,
dan carpenter




[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]
  Powered by Linux