Author: stuge Date: 2007-07-13 12:40:31 +0200 (Fri, 13 Jul 2007) New Revision: 453
Modified: LinuxBIOSv3/util/lar/extract.c LinuxBIOSv3/util/lar/lib.c LinuxBIOSv3/util/lar/lib.h Log: Replaces mkdirp() with mkdirp_below() that aborts directory creation and returns an error if any part of dirpath is located outside the specified parent directory. Use the parent "/" to allow new directories anywhere. Note that dirpath is relative to the working directory, not to parent.
Signed-off-by: Peter Stuge peter@stuge.se Acked-by: Stefan Reinauer stepan@coresystems.de
Modified: LinuxBIOSv3/util/lar/extract.c =================================================================== --- LinuxBIOSv3/util/lar/extract.c 2007-07-12 20:03:02 UTC (rev 452) +++ LinuxBIOSv3/util/lar/extract.c 2007-07-13 10:40:31 UTC (rev 453) @@ -119,7 +119,7 @@ if (pos) { pos[1] = 0; /* printf("Pathname %s\n",pathname); */ - mkdirp(pathname, 0755); + mkdirp_below(".", pathname, 0755); } free(pathname);
Modified: LinuxBIOSv3/util/lar/lib.c =================================================================== --- LinuxBIOSv3/util/lar/lib.c 2007-07-12 20:03:02 UTC (rev 452) +++ LinuxBIOSv3/util/lar/lib.c 2007-07-13 10:40:31 UTC (rev 453) @@ -24,6 +24,7 @@ #include <strings.h> #include <unistd.h> #include <dirent.h> +#include <errno.h> #include <sys/stat.h> #include <sys/types.h>
@@ -33,42 +34,82 @@
static struct file *files = NULL;
-int mkdirp(const char *dirpath, mode_t mode) +/** + * Create a new directory including any missing parent directories. + * + * NOTE: This function does not do complete path resolution as described in + * Linux path_resolution(2) and hence will fail for complex paths: + * + * e.g.: mkdirp_below("subdir", "subdir/../subdir/x", 0777); + * + * This call should create subdir/x, but since subdir/.. is outside subdir, + * the function returns an error. + * + * @param parent Return an error if a new directory would be created outside + * this directory. Pass "/" to allow new directories to be created anywhere. + * @param dirpath The new directory that should be created, the path can be + * either absolute or relative to the current working directory. (It is not + * relative to parent.) + * @param mode Permissions to use for newly created directories. + */ +int mkdirp_below(const char *parent, const char *dirpath, mode_t mode) { - char *pos, *currpath, *path; - char cwd[MAX_PATH]; - int ret = 0; + int ret = -1; + size_t dirsep, parlen, sublen; + char c, *r, *path = NULL, *subdir, rpar[PATH_MAX], rsub[PATH_MAX];
+ if (!dirpath) { + fprintf(stderr, "mkdirp_below: No new directory specified\n"); + goto done; + } + path = strdup(dirpath); if (!path) { - fprintf(stderr, "Out of memory.\n"); - exit(1); + perror("Duplicate new directory failed:"); + goto done; }
- currpath = path; - - if (!getcwd(cwd, MAX_PATH)) { - free(path); - fprintf(stderr, "Error getting cwd.\n"); - return -1; + if (NULL == realpath(parent, rpar)) { + fprintf(stderr, "realpath(%s) failed: %s\n", parent, + strerror(errno)); + goto done; } + parlen = strlen(rpar);
- do { - pos = index(currpath, '/'); - if (pos) - *pos = 0; + for (subdir = path, dirsep = 0; subdir[dirsep]; subdir += dirsep) { + dirsep = strcspn(subdir, "/\"); + if (!dirsep) { + subdir++; + continue; + }
- /* printf("cp=%s\n", currpath); */ - mkdir(currpath, mode); - ret = chdir(currpath); + c = subdir[dirsep]; + subdir[dirsep] = 0; + r = realpath(path, rsub); + sublen = strlen(rsub); + if (NULL == r) { + if(ENOENT != errno) { + fprintf(stderr, "realpath(%s) failed: %s\n", + path, strerror(errno)); + goto done; + } + } else if (sublen < parlen || strncmp(rpar, rsub, parlen)) { + fprintf(stderr, "Abort: %s is outside %s\n", dirpath, + parent); + goto done; + } + if(-1 == mkdir(path, mode) && EEXIST != errno) { + fprintf(stderr, "mkdir(%s): %s\n", path, + strerror(errno)); + goto done; + } + subdir[dirsep] = c; + } + ret = 0;
- if (pos) - currpath = pos + 1; - } while (pos && !ret && strlen(currpath)); - - chdir(cwd); - free(path); - +done: + if (path) + free(path); return ret; }
Modified: LinuxBIOSv3/util/lar/lib.h =================================================================== --- LinuxBIOSv3/util/lar/lib.h 2007-07-12 20:03:02 UTC (rev 452) +++ LinuxBIOSv3/util/lar/lib.h 2007-07-13 10:40:31 UTC (rev 453) @@ -41,7 +41,7 @@ char *get_bootblock(void);
/* prototypes for lib.c functions */ -int mkdirp(const char *dirpath, mode_t mode); +int mkdirp_below(const char *parent, const char *dirpath, mode_t mode);
int add_files(const char *name); int add_file_or_directory(const char *name);