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 <[EMAIL PROTECTED]>
Acked-by: Stefan Reinauer <[EMAIL PROTECTED]>


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);


-- 
linuxbios mailing list
[email protected]
http://www.linuxbios.org/mailman/listinfo/linuxbios

Reply via email to