[107521] trunk/base/src/darwintracelib1.0/darwintrace.c

cal at macports.org cal at macports.org
Mon Jul 1 17:58:26 PDT 2013


Revision: 107521
          https://trac.macports.org/changeset/107521
Author:   cal at macports.org
Date:     2013-07-01 17:58:26 -0700 (Mon, 01 Jul 2013)
Log Message:
-----------
darwintrace: factor out filemap iteration, reformat and cleanup file and path handling, fix bugs in path sanitizing, report more sandbox violations

Modified Paths:
--------------
    trunk/base/src/darwintracelib1.0/darwintrace.c

Modified: trunk/base/src/darwintracelib1.0/darwintrace.c
===================================================================
--- trunk/base/src/darwintracelib1.0/darwintrace.c	2013-07-02 00:47:57 UTC (rev 107520)
+++ trunk/base/src/darwintracelib1.0/darwintrace.c	2013-07-02 00:58:26 UTC (rev 107521)
@@ -350,14 +350,122 @@
 	return theCopy;
 }
 
-static void ask_for_filemap()
-{
-	filemap=exchange_with_port("filemap\t", sizeof("filemap\t"), 1);
-	if(filemap==(char*)-1)
-		filemap=0;
+/*
+ * Data structures and functions to iterate over the filemap received from
+ * tracelib code.
+ */
+/**
+ * \c filemap_iterator_t is an (opaque) iterator type that keeps the state
+ * required to iterate through the filemap. Create a new filemap_iterator_t on
+ * stack, initialize it using \c __darwintrace_filemap_iterator_init and pass
+ * it to \c __darwintrace_filemap_iter to iterate over the filemap.
+ */
+typedef struct filemap_iterator {
+	char *next;
+} filemap_iterator_t;
+
+/**
+ * Initialize a given \c filemap_iterator_t. Calling this function again will
+ * rewind the iterator.
+ *
+ * \param[in] it pointer to the iterator to be initialized
+ */
+__attribute__((always_inline))
+static inline void __darwintrace_filemap_iterator_init(filemap_iterator_t *it) {
+	it->next = filemap;
 }
 
+/**
+ * Iterate through the filemap passed from tracelib code. Call this multiple
+ * times with the same iterator object until it returns \c NULL to iterate
+ * through the filemap.
+ *
+ * \param[out] command location for the command specified for this filemap
+ *                     entry
+ * \param[out] replacement location for a replacement path, if any. This field
+ *                         is only valid if the command field indicates
+ *                         a replacement path is being used.
+ * \param[in]  it pointer to a \c filemap_iterator_t keeping the state of this
+ *                iteration
+ * \return string containing the path this filemap entry corresponds to, or \c
+ *         NULL if the end of the filemap was reached
+ */
 __attribute__((always_inline))
+static inline char *__darwintrace_filemap_iter(char *command, char **replacement, filemap_iterator_t *it) {
+	enum { PATH, COMMAND, REPLACEPATH, DONE } state = PATH;
+	char *t;
+	char *path;
+	
+	if (it == NULL || it->next == NULL || *it->next == '\0') {
+		return NULL;
+	}
+
+	path = t = it->next;
+
+	/* advance the cursor: if the number after the string is not 1, there's no
+	 * path behind it and we can advance by strlen(t) + 3. If it is 1, make
+	 * sure to skip the path, too.
+	 */
+	state = PATH;
+	while (state != DONE) {
+		switch (state) {
+			case DONE:
+				fprintf(stderr, "darwintrace: illegal state in dfa in " __FILE__ ":%d\n", __LINE__);
+				abort();
+				break;
+			case PATH:
+				if (!*t) {
+					state = COMMAND;
+				}
+				break;
+			case COMMAND:
+				*command = *t;
+				if (*t == 1) {
+					state = REPLACEPATH;
+					*replacement = t + 1;
+				} else {
+					state = DONE;
+					/* the byte after the status code is 0, if the status
+					 * code isn't 1 */
+					t++;
+				}
+				break;
+			case REPLACEPATH:
+				if (!*t) {
+					state = DONE;
+				}
+				break;
+		}
+		t++;
+	}
+
+	it->next = t;
+	return path;
+}
+
+/**
+ * Request sandbox boundaries from tracelib (the MacPorts base-controlled side
+ * of the trace setup) and store it.
+ */
+static void __darwintrace_get_filemap() {
+	filemap = exchange_with_port("filemap\t", sizeof("filemap\t"), 1);
+	if (filemap == (char*) -1)
+		filemap = 0;
+
+#	if 0
+	if (DARWINTRACE_DEBUG_OUTPUT) {
+		filemap_iterator_t it;
+		char *path, *replacement, command;
+
+		for (__darwintrace_filemap_iterator_init(&it);
+				(path = __darwintrace_filemap_iter(&command, &replacement, &it));) {
+			debug_printf("filemap: {cmd=%d, path=%-120s, replacement=%s}\n", command, path, (command == 1) ? replacement : "-");
+		}
+	}
+#	endif
+}
+
+__attribute__((always_inline))
 static inline void __darwintrace_setup() {
 #define open(x,y,z) syscall(SYS_open, (x), (y), (z))
 #define close(x) syscall(SYS_close, (x))
@@ -383,7 +491,7 @@
 			strncpy(sun.sun_path, __env_darwintrace_log, sizeof(sun.sun_path));
 			if (connect(sock, (struct sockaddr*)&sun, strlen(__env_darwintrace_log) + 1 + sizeof(sun.sun_family)) != -1) {
 				__darwintrace_fd = sock;
-				ask_for_filemap();
+				__darwintrace_get_filemap();
 			} else {
 				debug_printf("connect failed: %s\n", strerror(errno));
 				abort();
@@ -422,22 +530,22 @@
 	char logbuffer[BUFFER_SIZE];
 
 	do {
-#ifdef __APPLE__ /* Only Darwin has volfs and F_GETPATH */
-		if ((fd > 0) && (DARWINTRACE_LOG_FULL_PATH
-			|| (strncmp(path, "/.vol/", 6) == 0))) {
-			if(fcntl(fd, F_GETPATH, somepath) == -1) {
-				/* getpath failed. use somepath instead */
-				strlcpy(somepath, path, sizeof(somepath));
+#		ifdef __APPLE__ /* Only Darwin has volfs and F_GETPATH */
+		if ((fd > 0) && (DARWINTRACE_LOG_FULL_PATH || (strncmp(path, "/.vol/", 6) == 0))) {
+			if (fcntl(fd, F_GETPATH, somepath) != -1) {
 				break;
 			}
 		}
-#endif
-		if (path[0] != '/') {
-			int len;
-			(void) getcwd(somepath, sizeof(somepath));
-			len = strlen(somepath);
-			somepath[len++] = '/';
-			strlcpy(&somepath[len], path, sizeof(somepath) - len);
+#		endif
+
+		if (*path != '/') {
+			if (!getcwd(somepath, sizeof(somepath))) {
+				perror("darwintrace: getcwd");
+				abort();
+			}
+
+			strlcat(somepath, "/", sizeof(somepath));
+			strlcat(somepath, path, sizeof(somepath));
 			break;
 		}
 
@@ -600,39 +708,37 @@
 	}
 }
 
-#define DARWINTRACE_STATUS_PATH    ((char) 0)
-#define DARWINTRACE_STATUS_COMMAND ((char) 1)
-#define DARWINTRACE_STATUS_DONE    ((char) 2)
-
 /*
  * return 1 if path (once normalized) is in sandbox or redirected, 0 otherwise.
  */
 __attribute__((always_inline))
 static inline int __darwintrace_is_in_sandbox(const char* path, char * newpath) {
-	char *t, *p, *_;
+	char *t, *_;
 	char *strpos, *normpos;
 	char lpath[MAXPATHLEN];
 	char normalizedpath[MAXPATHLEN];
+	filemap_iterator_t filemap_it;
+	char command;
+	char *replacementpath;
 	
 	__darwintrace_setup();
 	
 	if (!filemap)
 		return 1;
 	
-	if (*path=='/') {
-		p = strcpy(lpath, path);
+	if (*path == '/') {
+		strcpy(lpath, path);
 	} else {
 		if (getcwd(lpath, MAXPATHLEN - 1) == NULL) {
-			fprintf(stderr, "darwintrace: getcwd: %s, path was: %s\n", strerror(errno), path);
+			perror("darwintrace: getcwd");
 			abort();
 		}
-		strcat(lpath, "/");
-		strcat(lpath, path);
+		strlcat(lpath, "/", MAXPATHLEN);
+		strlcat(lpath, path, MAXPATHLEN);
 	}
-	p = lpath;
 
 	normalizedpath[0] = '\0';
-	strpos = p + 1;
+	strpos = lpath + 1;
 	normpos = normalizedpath;
 	for (;;) {
 		char *curpos = strsep(&strpos, "/");
@@ -657,6 +763,7 @@
 			/* remove last component by overwriting the slash with \0, update normpos */
 			*lastSep = '\0';
 			normpos = lastSep;
+			continue;
 		}
 		/* default case: standard path, copy */
 		strcat(normpos, "/");
@@ -667,9 +774,8 @@
 		strcat(normalizedpath, "/");
 	}
 
-	for (t = filemap; *t;) {
-		char state;
-		
+	for (__darwintrace_filemap_iterator_init(&filemap_it);
+			(t = __darwintrace_filemap_iter(&command, &replacementpath, &filemap_it));) {
 		if (__darwintrace_pathbeginswith(normalizedpath, t)) {
 			/* move t to the integer describing how to handle this match */
 			t += strlen(t) + 1;
@@ -692,37 +798,17 @@
 					return 1;
 				case 2:
 					/* ask the socket whether this file is OK */
-					return ask_for_dependency(normalizedpath);
+					if (ask_for_dependency(normalizedpath)) {
+						return 1;
+					} else {
+						__darwintrace_log_op("sandbox_violation", normalizedpath, 0);
+						return 0;
+					}
 				default:
 					fprintf(stderr, "darwintrace: error: unexpected byte in file map: `%x'\n", *t);
 					abort();
 			}
 		}
-
-		/* advance the cursor: if the number after the string is not 1, there's
-		 * no path behind it and we can advance by strlen(t) + 3. If it is 1,
-		 * make sure to skip the path, too.
-		 */
-		state = DARWINTRACE_STATUS_PATH;
-		while (state != DARWINTRACE_STATUS_DONE) {
-			switch (state) {
-				case DARWINTRACE_STATUS_PATH:
-					if (!*t) {
-						state = DARWINTRACE_STATUS_COMMAND;
-					}
-					break;
-				case DARWINTRACE_STATUS_COMMAND:
-					if (*t == 1) {
-						state = DARWINTRACE_STATUS_PATH;
-						t++;
-					} else {
-						state = DARWINTRACE_STATUS_DONE;
-					}
-					break;
-			}
-			t++;
-		}
-		t++;
 	}
 
 	__darwintrace_log_op("sandbox_violation", normalizedpath, 0);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20130701/e42004a7/attachment.html>


More information about the macports-changes mailing list