[svn-commits] dlee: branch dlee/record r391287 - in /team/dlee/record: main/ tests/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Jun 10 11:35:03 CDT 2013


Author: dlee
Date: Mon Jun 10 11:35:00 2013
New Revision: 391287

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=391287
Log:
ast_safe_mkdir working as expected

Modified:
    team/dlee/record/main/utils.c
    team/dlee/record/tests/test_utils.c

Modified: team/dlee/record/main/utils.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/main/utils.c?view=diff&rev=391287&r1=391286&r2=391287
==============================================================================
--- team/dlee/record/main/utils.c (original)
+++ team/dlee/record/main/utils.c Mon Jun 10 11:35:00 2013
@@ -2109,30 +2109,58 @@
 		/* It is in the right place! */
 		return 0;
 	} else {
-		char *last_slash = strrchr(path, '/');
+		/* Path doesn't exist. */
+
+		/* The slash terminating the subpath we're checking */
+		char *path_term = strchr(path, '/');
+		/* True indicates the parent path is within base_path */
+		int parent_is_safe = 0;
 		int res;
 
-		if (last_slash == path) {
-			/* Parent is the root directory. */
-			res = EPERM;
-		} else if (last_slash == NULL) {
-			/* No more parents. */
-			res = EPERM;
-		} else {
-			/* Safely build the parent. */
-			*last_slash = '\0';
-			res = safe_mkdir(base_path, path, mode);
-			*last_slash = '/';
-		}
-
-		if (res != 0) {
-			/* Return failure */
-			errno = res;
-			return res;
-		}
-
-		/* Parent created, now create this path */
-		return safe_mkdir(base_path, path, mode);
+		while (path_term) {
+			RAII_VAR(char *, absolute_subpath, NULL, free);
+
+			/* Truncate the path one past the slash */
+			char c = *(path_term + 1);
+			*(path_term + 1) = '\0';
+			absolute_subpath = realpath(path, NULL);
+
+			if (absolute_subpath) {
+				/* Subpath exists, but is it safe? */
+				parent_is_safe = ast_begins_with(
+					absolute_subpath, base_path);
+			} else if (parent_is_safe) {
+				/* Subpath does not exist, but parent is safe
+				 * Create it */
+				res = mkdir(path, mode);
+				if (res != 0) {
+					ast_assert(errno != EEXIST);
+					return errno;
+				}
+			} else {
+				/* Subpath did not exist, parent was not safe
+				 * Fail! */
+				errno = EPERM;
+				return errno;
+			}
+			/* Restore the path */
+			*(path_term + 1) = c;
+			/* Move on to the next slash */
+			path_term = strchr(path_term + 1, '/');
+		}
+
+		/* Now to build the final path, but only if it's safe */
+		if (!parent_is_safe) {
+			errno = EPERM;
+			return errno;
+		}
+
+		res = mkdir(path, mode);
+		if (res != 0 && errno != EEXIST) {
+			return errno;
+		}
+
+		return 0;
 	}
 }
 
@@ -2142,17 +2170,19 @@
 	RAII_VAR(char *, p, NULL, ast_free);
 
 	if (base_path == NULL || path == NULL) {
-		return EFAULT;
+		errno = EFAULT;
+		return errno;
 	}
 
 	p = ast_strdup(path);
 	if (p == NULL) {
-		return ENOMEM;
+		errno = ENOMEM;
+		return errno;
 	}
 
 	absolute_base_path = realpath(base_path, NULL);
 	if (absolute_base_path == NULL) {
-		return ENOENT;
+		return errno;
 	}
 
 	return safe_mkdir(absolute_base_path, p, mode);

Modified: team/dlee/record/tests/test_utils.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/tests/test_utils.c?view=diff&rev=391287&r1=391286&r2=391287
==============================================================================
--- team/dlee/record/tests/test_utils.c (original)
+++ team/dlee/record/tests/test_utils.c Mon Jun 10 11:35:00 2013
@@ -498,7 +498,7 @@
 	ast_test_validate(test, ENOENT == errno);
 
 	snprintf(path, sizeof(path),
-		"%s/this/especially/should/not/../../../../work", base_path);
+		"%s/this/especially/should/not/../../../../../work", base_path);
 	res = ast_safe_mkdir(base_path, path, 0777);
 	ast_test_validate(test, 0 != res);
 	ast_test_validate(test, EPERM == errno);




More information about the svn-commits mailing list