[PATCH v3] cmd: sf: prevent overwriting the reserved memory
Sughosh Ganu
sughosh.ganu at linaro.org
Wed Sep 11 13:56:15 CEST 2024
On Wed, 11 Sept 2024 at 17:02, Michal Simek <michal.simek at amd.com> wrote:
>
>
>
> On 9/11/24 13:29, Sughosh Ganu wrote:
> > On Wed, 11 Sept 2024 at 16:53, Michal Simek <michal.simek at amd.com> wrote:
> >>
> >>
> >>
> >> On 9/11/24 13:20, Sughosh Ganu wrote:
> >>> On Tue, 10 Sept 2024 at 21:14, Prasad Kummari <prasad.kummari at amd.com> wrote:
> >>>>
> >>>> Added LMB API to prevent SF command from overwriting reserved
> >>>> memory areas. The current SPI code does not use LMB APIs for
> >>>> loading data into memory addresses. To resolve this, LMB APIs
> >>>> were added to check the load address of an SF command and ensure it
> >>>> does not overwrite reserved memory addresses. Similar checks are
> >>>> used in TFTP, serial load, and boot code to prevent overwriting
> >>>> reserved memory.
> >>>>
> >>>> Signed-off-by: Prasad Kummari <prasad.kummari at amd.com>
> >>>> ---
> >>>>
> >>>> Changes in V3:
> >>>> - Removed lmb_init_and_reserve() as part of latest LMB series.
> >>>> - Error message moved to one place.
> >>>> - lmb_alloc_addr() is not required because the given memory address is
> >>>> being checked to ensure it is free or not.
> >>>>
> >>>> Changes in V2:
> >>>> - Rebased the code changes on top of the next branch.
> >>>>
> >>>> UT:
> >>>> Tested on Versal NET board
> >>>>
> >>>> Versal NET> fdt print /reserved-memory
> >>>> reserved-memory {
> >>>> ranges;
> >>>> #size-cells = <0x00000002>;
> >>>> #address-cells = <0x00000002>;
> >>>> tf-a {
> >>>> reg = <0x00000000 0x70000000 0x00000000 0x00050000>;
> >>>> no-map;
> >>>> };
> >>>> };
> >>>> Versal NET> sf read 0x70000000 0x0 0x40
> >>>> device 0 offset 0x0, size 0x40
> >>>> ERROR: trying to overwrite reserved memory...
> >>>>
> >>>> Versal NET> sf write 0x70000000 0x0 0x40
> >>>> device 0 offset 0x0, size 0x40
> >>>> ERROR: trying to overwrite reserved memory...
> >>>>
> >>>> relocaddr = 0x000000007febc000
> >>>>
> >>>> Versal NET> sf read 0x000000007febc000 0x0 0x40
> >>>> device 0 offset 0x0, size 0x40
> >>>> ERROR: trying to overwrite reserved memory...
> >>>>
> >>>> Versal NET> sf write 0x000000007febc000 0x0 0x40
> >>>> device 0 offset 0x0, size 0x40
> >>>> ERROR: trying to overwrite reserved memory...
> >>>>
> >>>> cmd/sf.c | 36 +++++++++++++++++++++++++++++++++++-
> >>>> 1 file changed, 35 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/cmd/sf.c b/cmd/sf.c
> >>>> index f43a2e08b3..7bb8bcfce2 100644
> >>>> --- a/cmd/sf.c
> >>>> +++ b/cmd/sf.c
> >>>> @@ -10,6 +10,7 @@
> >>>> #include <div64.h>
> >>>> #include <dm.h>
> >>>> #include <log.h>
> >>>> +#include <lmb.h>
> >>>> #include <malloc.h>
> >>>> #include <mapmem.h>
> >>>> #include <spi.h>
> >>>> @@ -272,6 +273,31 @@ static int spi_flash_update(struct spi_flash *flash, u32 offset,
> >>>> return 0;
> >>>> }
> >>>>
> >>>> +#ifdef CONFIG_LMB
> >>>> +static int do_spi_read_lmb_check(ulong start_addr, loff_t len)
> >>>> +{
> >>>> + phys_size_t max_size;
> >>>> + ulong end_addr;
> >>>> +
> >>>> + lmb_dump_all();
> >>>> +
> >>>> + max_size = lmb_get_free_size(start_addr);
> >>>> + if (!max_size) {
> >>>> + return CMD_RET_FAILURE;
> >>>> + }
> >>>> +
> >>>> + end_addr = start_addr + max_size;
> >>>> + if (!end_addr)
> >>>> + end_addr = ULONG_MAX;
> >>>> +
> >>>> + if ((start_addr + len) > end_addr) {
> >>>> + return CMD_RET_FAILURE;
> >>>> + }
> >>>
> >>> This is one way to get the load address, yes. But please do note that
> >>> with this method, if the region of memory has already been marked as
> >>> reserved, the call to lmb_get_free_size() will fail, i.e. return a
> >>> value of 0. Whereas if you call lmb_alloc_addr(), and if the memory
> >>> region is marked reserved with the flags set to LMB_NONE, that call
> >>> will not fail, as we can re-reserve memory marked as LMB_NONE. Hence a
> >>> better approach would be to use the logic used in the fs module
> >>> function that I had pointed to in my earlier email.
> >>>
> >>> Also, like I mentioned earlier, it will be better to refactor the
> >>> functionality, especially if the plan is to introduce this check for
> >>> loading stuff through other interfaces like nand, mmc etc. You can add
> >>> a function in the lmb.c like lmb_read_check() which does that.
> >>
> >> Is this something what you are going to work on?
> >
> > Can that not be done as part of this work? It is about having a single
> > function in the lmb.c file, which simply does a check for
> > lmb_alloc_addr(). It's not very complicated tbh.
>
> It is more about time spent on it. If you know how exactly it should look like
> it would be easier for you to put it together and Prasad can validate it on our
> platforms.
Prasad, Can you try this change? If this works, you can use this. I
will work on using this in other functions later.
diff --git a/cmd/sf.c b/cmd/sf.c
index 7bb8bcfce2..33d88a3531 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -343,13 +343,12 @@ static int do_spi_flash_read_write(int argc,
char *const argv[])
strncmp(argv[0], "write", 5) == 0) {
int read, ret;
-#ifdef CONFIG_LMB
- ret = do_spi_read_lmb_check(addr, len);
- if (ret) {
- printf("ERROR: trying to overwrite reserved
memory...\n");
- return ret;
+ if (CONFIG_IS_ENABLED(LMB)) {
+ if (lmb_read_check(addr, len)) {
+ printf("ERROR: trying to overwrite
reserved memory...\n");
+ return CMD_RET_FAILURE;
+ }
}
-#endif
read = strncmp(argv[0], "read", 4) == 0;
if (read)
diff --git a/include/lmb.h b/include/lmb.h
index 6ef03f9b63..601055a837 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -122,6 +122,11 @@ struct lmb *lmb_get(void);
int lmb_push(struct lmb *store);
void lmb_pop(struct lmb *store);
+static inline int lmb_read_check(phys_addr_t addr, phys_size_t len)
+{
+ return lmb_alloc_addr(addr, len) == addr ? 0 : -1;
+}
+
#endif /* __KERNEL__ */
#endif /* _LINUX_LMB_H */
-sughosh
More information about the U-Boot
mailing list