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>


git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@453 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
Peter Stuge 2007-07-13 10:40:31 +00:00
parent 7e5b9406af
commit 7f49e38558
3 changed files with 71 additions and 30 deletions

View file

@ -119,7 +119,7 @@ int extract_lar(const char *archivename, struct file *files)
if (pos) {
pos[1] = 0;
/* printf("Pathname %s\n",pathname); */
mkdirp(pathname, 0755);
mkdirp_below(".", pathname, 0755);
}
free(pathname);

View file

@ -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 (NULL == realpath(parent, rpar)) {
fprintf(stderr, "realpath(%s) failed: %s\n", parent,
strerror(errno));
goto done;
}
parlen = strlen(rpar);
if (!getcwd(cwd, MAX_PATH)) {
for (subdir = path, dirsep = 0; subdir[dirsep]; subdir += dirsep) {
dirsep = strcspn(subdir, "/\\");
if (!dirsep) {
subdir++;
continue;
}
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;
done:
if (path)
free(path);
fprintf(stderr, "Error getting cwd.\n");
return -1;
}
do {
pos = index(currpath, '/');
if (pos)
*pos = 0;
/* printf("cp=%s\n", currpath); */
mkdir(currpath, mode);
ret = chdir(currpath);
if (pos)
currpath = pos + 1;
} while (pos && !ret && strlen(currpath));
chdir(cwd);
free(path);
return ret;
}

View file

@ -41,7 +41,7 @@ long get_larsize(void);
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);