Message ID | 20200819172134.11243-3-nramas@linux.microsoft.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Carry forward IMA measurement log on kexec on ARM64 | expand |
Lakshmi Ramasubramanian <nramas@linux.microsoft.com> writes: > @@ -63,7 +29,22 @@ void remove_ima_buffer(void *fdt, int chosen_node) > if (!prop) > return; > > - ret = do_get_kexec_buffer(prop, len, &addr, &size); > + ret = fdt_address_cells(fdt, chosen_node); This change was already present in the previous version of the patch but it was just today that I noticed a problem: there's no #address-cells property in /chosen. This code will still work though because if there's no property this function returns 2 which is the correct value for ppc64. But it's conceptually wrong. You need to pass the node offset for / so that it gets the #address-cells property from there. > + if (ret < 0) > + return; > + addr_cells = ret; > + > + ret = fdt_size_cells(fdt, chosen_node); Here we're not so lucky. The default value returned when no #size-cells property is present is 1, which is wrong for ppc64 so this change introduces a bug. You also need to pass the node offset for / here. > + if (ret < 0) > + return; > + size_cells = ret; > + > + if (len < 4 * (addr_cells + size_cells)) > + return; > + > + addr = of_read_number(prop, addr_cells); > + size = of_read_number(prop + 4 * addr_cells, size_cells); > + > fdt_delprop(fdt, chosen_node, FDT_PROP_IMA_KEXEC_BUFFER); > if (ret) > return; > @@ -129,9 +110,15 @@ int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node) > if (!image->arch.ima_buffer_size) > return 0; > > - ret = get_addr_size_cells(&addr_cells, &size_cells); > - if (ret) > + ret = fdt_address_cells(fdt, chosen_node); > + if (ret < 0) > + return ret; > + addr_cells = ret; > + > + ret = fdt_size_cells(fdt, chosen_node); > + if (ret < 0) > return ret; > + size_cells = ret; > > entry_size = 4 * (addr_cells + size_cells); Ditto here.
On 8/27/20 4:50 PM, Thiago Jung Bauermann wrote: > > Lakshmi Ramasubramanian <nramas@linux.microsoft.com> writes: > >> @@ -63,7 +29,22 @@ void remove_ima_buffer(void *fdt, int chosen_node) >> if (!prop) >> return; >> >> - ret = do_get_kexec_buffer(prop, len, &addr, &size); >> + ret = fdt_address_cells(fdt, chosen_node); > > This change was already present in the previous version of the patch but > it was just today that I noticed a problem: there's no #address-cells > property in /chosen. This code will still work though because if there's > no property this function returns 2 which is the correct value for > ppc64. But it's conceptually wrong. You need to pass the node offset for > / so that it gets the #address-cells property from there. Thanks for the info. Will fix this. > >> + if (ret < 0) >> + return; >> + addr_cells = ret; >> + >> + ret = fdt_size_cells(fdt, chosen_node); > > Here we're not so lucky. The default value returned when no #size-cells > property is present is 1, which is wrong for ppc64 so this change > introduces a bug. You also need to pass the node offset for / here. Will fix this. > >> + if (ret < 0) >> + return; >> + size_cells = ret; >> + >> + if (len < 4 * (addr_cells + size_cells)) >> + return; >> + >> + addr = of_read_number(prop, addr_cells); >> + size = of_read_number(prop + 4 * addr_cells, size_cells); >> + >> fdt_delprop(fdt, chosen_node, FDT_PROP_IMA_KEXEC_BUFFER); >> if (ret) >> return; >> @@ -129,9 +110,15 @@ int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node) >> if (!image->arch.ima_buffer_size) >> return 0; >> >> - ret = get_addr_size_cells(&addr_cells, &size_cells); >> - if (ret) >> + ret = fdt_address_cells(fdt, chosen_node); >> + if (ret < 0) >> + return ret; >> + addr_cells = ret; >> + >> + ret = fdt_size_cells(fdt, chosen_node); >> + if (ret < 0) >> return ret; >> + size_cells = ret; >> >> entry_size = 4 * (addr_cells + size_cells); > > Ditto here. > Will fix this. thanks, -lakshmi
diff --git a/arch/powerpc/kexec/ima.c b/arch/powerpc/kexec/ima.c index f5112ee4bb0b..573ff708d700 100644 --- a/arch/powerpc/kexec/ima.c +++ b/arch/powerpc/kexec/ima.c @@ -12,40 +12,6 @@ #include <linux/memblock.h> #include <linux/libfdt.h> -static int get_addr_size_cells(int *addr_cells, int *size_cells) -{ - struct device_node *root; - - root = of_find_node_by_path("/"); - if (!root) - return -EINVAL; - - *addr_cells = of_n_addr_cells(root); - *size_cells = of_n_size_cells(root); - - of_node_put(root); - - return 0; -} - -static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr, - size_t *size) -{ - int ret, addr_cells, size_cells; - - ret = get_addr_size_cells(&addr_cells, &size_cells); - if (ret) - return ret; - - if (len < 4 * (addr_cells + size_cells)) - return -ENOENT; - - *addr = of_read_number(prop, addr_cells); - *size = of_read_number(prop + 4 * addr_cells, size_cells); - - return 0; -} - /** * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt * @@ -54,7 +20,7 @@ static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr, */ void remove_ima_buffer(void *fdt, int chosen_node) { - int ret, len; + int ret, len, addr_cells, size_cells; unsigned long addr; size_t size; const void *prop; @@ -63,7 +29,22 @@ void remove_ima_buffer(void *fdt, int chosen_node) if (!prop) return; - ret = do_get_kexec_buffer(prop, len, &addr, &size); + ret = fdt_address_cells(fdt, chosen_node); + if (ret < 0) + return; + addr_cells = ret; + + ret = fdt_size_cells(fdt, chosen_node); + if (ret < 0) + return; + size_cells = ret; + + if (len < 4 * (addr_cells + size_cells)) + return; + + addr = of_read_number(prop, addr_cells); + size = of_read_number(prop + 4 * addr_cells, size_cells); + fdt_delprop(fdt, chosen_node, FDT_PROP_IMA_KEXEC_BUFFER); if (ret) return; @@ -129,9 +110,15 @@ int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node) if (!image->arch.ima_buffer_size) return 0; - ret = get_addr_size_cells(&addr_cells, &size_cells); - if (ret) + ret = fdt_address_cells(fdt, chosen_node); + if (ret < 0) + return ret; + addr_cells = ret; + + ret = fdt_size_cells(fdt, chosen_node); + if (ret < 0) return ret; + size_cells = ret; entry_size = 4 * (addr_cells + size_cells);