[U-Boot] [PATCH 0/3] cramfs fixes and symlink support

This adds initial support for symlinks in cramfs and fixes cramfs so that it can be tested in the sandbox. "cramfs: block pointers are 32 bits" fixes a crash on 64-bit which I have experienced on ARMv8 as well as the sandbox.
Tyler Hall (3): cmd: cramfs: use map_sysmem for sandbox support cramfs: block pointers are 32 bits cramfs: basic symlink support
cmd/cramfs.c | 13 ++++++++--- fs/cramfs/cramfs.c | 64 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 61 insertions(+), 16 deletions(-)

As with most other commands, this needs to factor in the sysmem offset in the sandbox or it will try to dereference the simulated physical address directly.
Signed-off-by: Tyler Hall tylerwhall@gmail.com --- cmd/cramfs.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/cmd/cramfs.c b/cmd/cramfs.c index 965ca4e60d..34be8554a7 100644 --- a/cmd/cramfs.c +++ b/cmd/cramfs.c @@ -18,6 +18,7 @@ #include <jffs2/jffs2.h> #include <jffs2/load_kernel.h> #include <cramfs/cramfs_fs.h> +#include <asm/io.h>
/* enable/disable debugging messages */ #define DEBUG_CRAMFS @@ -95,6 +96,7 @@ int do_cramfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) char *filename; int size; ulong offset = load_addr; + char *offset_virt;
struct part_info part; struct mtd_device dev; @@ -111,7 +113,7 @@ int do_cramfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) dev.id = &id; part.dev = &dev; /* fake the address offset */ - part.offset = addr - OFFSET_ADJUSTMENT; + part.offset = (u64) map_sysmem(addr - OFFSET_ADJUSTMENT, 0);
/* pre-set Boot file name */ if ((filename = getenv("bootfile")) == NULL) { @@ -127,9 +129,10 @@ int do_cramfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) filename = argv[2]; }
+ offset_virt = map_sysmem(offset, 0); size = 0; if (cramfs_check(&part)) - size = cramfs_load ((char *) offset, &part, filename); + size = cramfs_load (offset_virt, &part, filename);
if (size > 0) { printf("### CRAMFS load complete: %d bytes loaded to 0x%lx\n", @@ -139,6 +142,9 @@ int do_cramfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("### CRAMFS LOAD ERROR<%x> for %s!\n", size, filename); }
+ unmap_sysmem(offset_virt); + unmap_sysmem((void *)part.offset); + return !(size > 0); }
@@ -172,7 +178,7 @@ int do_cramfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) dev.id = &id; part.dev = &dev; /* fake the address offset */ - part.offset = addr - OFFSET_ADJUSTMENT; + part.offset = (u64) map_sysmem(addr - OFFSET_ADJUSTMENT, 0);
if (argc == 2) filename = argv[1]; @@ -180,6 +186,7 @@ int do_cramfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ret = 0; if (cramfs_check(&part)) ret = cramfs_ls (&part, filename); + unmap_sysmem((void *)part.offset);
return ret ? 0 : 1; }

On Wed, Mar 22, 2017 at 04:02:04PM -0400, Tyler Hall wrote:
As with most other commands, this needs to factor in the sysmem offset in the sandbox or it will try to dereference the simulated physical address directly.
Signed-off-by: Tyler Hall tylerwhall@gmail.com
This series introduces a few problems such as kmopti2 not building. Please use travis-ci to get a most-of-the-world build done prior to resubmission, thanks!

Using a variably-sized type is incorrect here since we're reading a fixed file format. Fixes cramfs on 64-bit platforms.
Signed-off-by: Tyler Hall tylerwhall@gmail.com --- fs/cramfs/cramfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index 05ed27240a..ca8bc5e12b 100644 --- a/fs/cramfs/cramfs.c +++ b/fs/cramfs/cramfs.c @@ -162,7 +162,7 @@ static int cramfs_uncompress (unsigned long begin, unsigned long offset, unsigned long loadoffset) { struct cramfs_inode *inode = (struct cramfs_inode *) (begin + offset); - unsigned long *block_ptrs = (unsigned long *) + u32 *block_ptrs = (u32 *) (begin + (CRAMFS_GET_OFFSET (inode) << 2)); unsigned long curr_block = (CRAMFS_GET_OFFSET (inode) + (((CRAMFS_24 (inode->size)) +

Handle symlinks to files in the current directory. Other cases could be handled with additional code, but this is a start.
Add explicit errors for absolute paths and links found in the middle of a path (directories). Other cases like '..' or '.' will result with the file not being found as when those path components are explicitly provided.
Add a helper to decompress a null-terminated link name which is shared with cramfs_list_inode.
Signed-off-by: Tyler Hall tylerwhall@gmail.com --- fs/cramfs/cramfs.c | 62 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 12 deletions(-)
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index ca8bc5e12b..228f599d44 100644 --- a/fs/cramfs/cramfs.c +++ b/fs/cramfs/cramfs.c @@ -49,6 +49,9 @@ extern flash_info_t flash_info[]; #define PART_OFFSET(x) ((ulong)x->offset) #endif
+static int cramfs_uncompress (unsigned long begin, unsigned long offset, + unsigned long loadoffset); + static int cramfs_read_super (struct part_info *info) { unsigned long root_offset; @@ -94,6 +97,22 @@ static int cramfs_read_super (struct part_info *info) return 0; }
+/* Unpack to an allocated buffer, trusting in the inode's size field. */ +static char *cramfs_uncompress_link (unsigned long begin, unsigned long offset) +{ + struct cramfs_inode *inode = (struct cramfs_inode *)(begin + offset); + unsigned long size = CRAMFS_24 (inode->size); + char *link = malloc (size + 1); + + if (!link || cramfs_uncompress (begin, offset, (unsigned long)link) != size) { + free (link); + link = NULL; + } else { + link[size] = '\0'; + } + return link; +} + static unsigned long cramfs_resolve (unsigned long begin, unsigned long offset, unsigned long size, int raw, char *filename) @@ -143,6 +162,33 @@ static unsigned long cramfs_resolve (unsigned long begin, unsigned long offset, p); } else if (S_ISREG (CRAMFS_16 (inode->mode))) { return offset + inodeoffset; + } else if (S_ISLNK (CRAMFS_16 (inode->mode))) { + unsigned long ret; + char *link; + if (p && strlen(p)) { + printf ("unsupported symlink to \ + non-terminal path\n"); + return 0; + } + link = cramfs_uncompress_link (begin, + offset + inodeoffset); + if (!link) { + printf ("%*.*s: Error reading link\n", + namelen, namelen, name); + return 0; + } else if (link[0] == '/') { + printf ("unsupported symlink to \ + absolute path\n"); + free (link); + return 0; + } + ret = cramfs_resolve (begin, + offset, + size, + raw, + strtok(link, "/")); + free (link); + return ret; } else { printf ("%*.*s: unsupported file type (%x)\n", namelen, namelen, name, @@ -235,20 +281,12 @@ static int cramfs_list_inode (struct part_info *info, unsigned long offset) CRAMFS_24 (inode->size), namelen, namelen, name);
if ((CRAMFS_16 (inode->mode) & S_IFMT) == S_IFLNK) { - /* symbolic link. - * Unpack the link target, trusting in the inode's size field. - */ - unsigned long size = CRAMFS_24 (inode->size); - char *link = malloc (size); - - if (link != NULL && cramfs_uncompress (PART_OFFSET(info), offset, - (unsigned long) link) - == size) - printf (" -> %*.*s\n", (int) size, (int) size, link); + char *link = cramfs_uncompress_link (PART_OFFSET(info), offset); + if (link) + printf (" -> %s\n", link); else printf (" [Error reading link]\n"); - if (link) - free (link); + free (link); } else printf ("\n");
participants (2)
-
Tom Rini
-
Tyler Hall