<pre style='margin:0'>
Clemens Lang (neverpanic) pushed a commit to branch master
in repository macports-base.
</pre>
<p><a href="https://github.com/macports/macports-base/commit/eee415ad29ec3c9535ad02cd1d52d9f853c32b85">https://github.com/macports/macports-base/commit/eee415ad29ec3c9535ad02cd1d52d9f853c32b85</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit eee415ad29ec3c9535ad02cd1d52d9f853c32b85
</span>Author: Clemens Lang <cal@macports.org>
AuthorDate: Fri Dec 18 15:24:06 2020 +0100
<span style='display:block; white-space:pre;color:#404040;'> darwintrace: Support arbitrary path lengths
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> darwintrace.dylib did occasionally crash in __darwintrace_is_in_sandbox
</span><span style='display:block; white-space:pre;color:#404040;'> due to stack canary violations, because the reimplementation of realpath
</span><span style='display:block; white-space:pre;color:#404040;'> and splitting into path components assumed that paths will not be longer
</span><span style='display:block; white-space:pre;color:#404040;'> than MAXPATHLEN. In practice, this assumption was wrong, and many build
</span><span style='display:block; white-space:pre;color:#404040;'> systems will invoke file system operations with paths longer than that.
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> Switch to dynamically allocated strings and arrays and resize the
</span><span style='display:block; white-space:pre;color:#404040;'> buffers as necessary. This also simplifies the code significantly and
</span><span style='display:block; white-space:pre;color:#404040;'> fixes a number of corner cases that were previously not handled
</span><span style='display:block; white-space:pre;color:#404040;'> correctly, such as walking up past the root directory or multiple
</span><span style='display:block; white-space:pre;color:#404040;'> slashes in a row.
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> With these changes, quassel builds successfully in trace mode – without
</span><span style='display:block; white-space:pre;color:#404040;'> them, the build abort(3)s.
</span>---
src/darwintracelib1.0/darwintrace.c | 569 ++++++++++++++++++++++++------------
1 file changed, 375 insertions(+), 194 deletions(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/darwintracelib1.0/darwintrace.c b/src/darwintracelib1.0/darwintrace.c
</span><span style='display:block; white-space:pre;color:#808080;'>index cbc92b3bc..71ba17e1d 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/darwintracelib1.0/darwintrace.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/darwintracelib1.0/darwintrace.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -713,66 +713,300 @@ static inline bool __darwintrace_sandbox_check(const char *path, int flags) {
</span> return false;
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>-/* Private struct for __darwintrace_is_in_sandbox */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Structure to represent a filesystem path component, i.e., a single level of a path.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span> typedef struct {
<span style='display:block; white-space:pre;background:#ffe0e0;'>- char *start;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *path;
</span> size_t len;
} path_component_t;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-/*
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * Helper function for __darwintrace_is_in_sandbox.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Structure to represent a normalized filesystem path.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+typedef struct {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t num;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t capacity;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_component_t *components;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+} path_t;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define PATH_INITIAL_CAPACITY (PATH_MAX / 4 + 2)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Allocate a new filesystem path structure.
</span> *
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * \param[in] token path to parse
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * \param[in] dst write position in normPath buffer
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * \param[in] numComponents number of parsed components
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * \param[in,out] pathComponents array of parsed components
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * \param[out] normPath output buffer
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * \return next numComponents
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-static size_t __parse_path_normalize(const char *token, char *dst, size_t numComponents, path_component_t *pathComponents, char *normPath) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- size_t idx;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- while ((idx = strcspn(token, "/")) > 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // found a token, process it
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (token[0] == '\0' || token[0] == '/') {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // empty entry, ignore
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else if (token[0] == '.' && (token[1] == '\0' || token[1] == '/')) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // reference to current directory, ignore
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else if (token[0] == '.' && token[1] == '.' && (token[2] == '\0' || token[2] == '/')) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // walk up one directory, but not if it's the last one, because /.. -> /
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (numComponents > 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents--;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (numComponents > 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // move dst back to the previous entry
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- path_component_t *lastComponent = pathComponents + (numComponents - 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst = lastComponent->start + lastComponent->len + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // we're at the top, move dst back to the beginning
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst = normPath + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @return Pointer to the new path_t on success, NULL on error.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static path_t *path_new() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_t *path = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path = malloc(sizeof(path_t));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ goto out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->num = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->capacity = PATH_INITIAL_CAPACITY;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->components = malloc(sizeof(path_component_t) * path->capacity);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path->components) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+out:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Free a filesystem path structure.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] path The path to release.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static void path_free(path_t *path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (size_t idx = 0; idx < path->num; ++idx) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path->components[idx].path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path->components);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Append a component (given as string) to an existing filesystem path while
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * preserving normality.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * If the given component is empty, or ".", the path will remain unmodified. If
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * the given component is "..", the last component of the path is deleted.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Otherwise, the new component is appended to the end of the path. Note that
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * component must NOT contain slashes.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] path The path to which the component should be appended.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] component The path component to append.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @return true on success, false when memory allocation fails.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static bool path_append(path_t *path, const char *component) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (*component == '\0') {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // ignore empty path components, i.e., consecutive slashes
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return true;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else if (component[0] == '.' && component[1] == '\0') {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // ignore self-referencing path components
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return true;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else if (component[0] == '.' && component[1] == '.' && component[2] == '\0') {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // walk up one path component, if possible
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (path->num > 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path->components[path->num - 1].path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->num--;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (path->num >= path->capacity) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // need more space for components, realloc to make that space
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t new_capacity = path->capacity + (PATH_INITIAL_CAPACITY / 2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_component_t *new_components = realloc(path->components, sizeof(path_component_t) * new_capacity);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!new_components) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return false;
</span> }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // copy token to normPath buffer (and null-terminate it)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- strlcpy(dst, token, idx + 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst[idx] = '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // add descriptor entry for new token
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[numComponents].start = dst;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[numComponents].len = idx;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents++;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // advance destination
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst += idx + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->capacity = new_capacity;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->components = new_components;
</span> }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- if (token[idx] == '\0') {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // initialize new path_component_t
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t len = strlen(component);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_component_t *new_component = &path->components[path->num];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ new_component->len = len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ new_component->path = malloc(len + 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!new_component->path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return false;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ strlcpy(new_component->path, component, len + 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->num++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return true;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Take the given input path as string, tokenize it into separate path
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * components, then append them to the given path, normalizing the path in the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * process. Modifies the given inpath string.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] path The path to which the new components should be appended.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] inpath The string input path which will be tokenized and normalized.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @return true on success, false on memory allocation failure.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static bool path_tokenize(path_t *path, char *inpath) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *pos = inpath;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ const char *token;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ while ((token = strsep(&pos, "/")) != NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_append(path, token)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return false;
</span> }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- token += idx + 1;
</span> }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- return numComponents;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return true;
</span> }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * The the given symbolic link as string, tokenize it into separate path
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * components and normalize it in the context of the given path. If the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * symbolic link is absolute, this will replace the entire path, otherwise
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * normalize the symlink relative to the current path. Modifies the given link.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] path The path relative to which the symlink should be interpreted.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] link The symbolic link contents obtained from readlink(2).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @return true on success, false on memory allocation failure.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static bool path_tokenize_symlink(path_t *path, char *link) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (*link == '/') {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // symlink is absolute, start fresh
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (size_t idx = 0; idx < path->num; idx++) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path->components[idx].path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->num = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return path_tokenize(path, link + 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // symlink is relative, remove last component
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (path->num > 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path->components[path->num - 1].path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->num--;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return path_tokenize(path, link);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Strip a resource fork from the end of the path, if present.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] path The path which should be checked for resource forks
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static void path_strip_resource_fork(path_t *path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (path->num >= 2) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if ( strcmp(path->components[path->num - 2].path, "..namedfork") == 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ && strcmp(path->components[path->num - 1].path, "rsrc") == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path->components[path->num - 2].path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path->components[path->num - 1].path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path->num -= 2;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Return the length of the given path when represented as a native filesystem
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * path with "/" separators, excluding the terminating \0 byte.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] path The path whose length should be determined.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @return The length of the path.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static size_t path_len(const path_t *path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // One slash for each component
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t len = path->num;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // Plus the length for each component
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (size_t idx = 0; idx < path->num; ++idx) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ len += path->components[idx].len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Convert the given path into a string. The returned pointer is allocated and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * must be released with free(3).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] path The path to convert to a string.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @return An allocated string representation of the path on success, NULL on error.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static char *path_str(const path_t *path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t len = path_len(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *out = malloc(len + 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!out) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ out[0] = '/';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ out[1] = '\0';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *pos = out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (size_t idx = 0; idx < path->num; idx++) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *pos = '/';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ pos++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_component_t *component = &path->components[idx];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ strlcpy(pos, component->path, component->len + 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ pos += component->len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Check whether the given path is a volfs path (i.e., /.vol/$fsnum/$inode),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * and return a non-volfs path if possible.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * If the return value is not the argument, the argument was correctly freed.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Always use this function as
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * path = path_resolve_volfs(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * for this reason.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param[in] path The path to check for volfs paths
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @return The orginal path if no modification was required or expansion
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * failed. A fresh path if the path was a volfs path and was expanded.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static path_t *path_resolve_volfs(path_t *path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifdef ATTR_CMN_FULLPATH
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (path->num >= 3 && strcmp(path->components[0].path, ".vol") == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct attrlist attrlist;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ attrlist.reserved = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ attrlist.commonattr = ATTR_CMN_FULLPATH;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ attrlist.volattr = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ attrlist.dirattr = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ attrlist.fileattr = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ attrlist.forkattr = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char attrbuf[sizeof(uint32_t) + sizeof(attrreference_t) + (PATH_MAX + 1)];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* attrlength attrref_t for the name UTF-8 name up to PATH_MAX chars */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *path_native = path_str(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_native) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ goto out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (-1 == (getattrlist(path_native, &attrlist, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: getattrlist");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // ignore and just return the /.vol/ path
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_t *newpath = path_new();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!newpath) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ goto out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ attrreference_t *nameAttrRef = (attrreference_t *) (attrbuf + sizeof(uint32_t));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_tokenize(newpath, ((char *) nameAttrRef) + nameAttrRef->attr_dataoffset)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_free(newpath);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ goto out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_free(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path = newpath;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+out:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path_native);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* defined(ATTR_CMN_FULLPATH) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /**
* Check a path against the current sandbox
*
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -795,27 +1029,24 @@ bool __darwintrace_is_in_sandbox(const char *path, int flags) {
</span> return true;
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>- char normPath[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- normPath[0] = '/';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- normPath[1] = '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- path_component_t pathComponents[MAXPATHLEN / 2 + 2];
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- size_t numComponents = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // Make sure the path is absolute.
</span> if (path == NULL || *path == '\0') {
// this is most certainly invalid, let the syscall deal with it
return true;
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>- char *dst = NULL;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- const char *token = NULL;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- size_t idx;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_t *normPath = path_new();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!normPath) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: path_new");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t offset = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> if (*path != '/') {
/*
* The path isn't absolute, start by populating pathcomponents with the
* current working directory.
<span style='display:block; white-space:pre;background:#ffe0e0;'>- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span> * However, we avoid getcwd(3) if we can and use getattrlist(2) with
* ATTR_CMN_FULLPATH instead, because getcwd(3) will open all parent
* directories, read them, search for the current component using its
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -833,134 +1064,68 @@ bool __darwintrace_is_in_sandbox(const char *path, int flags) {
</span> attrlist.fileattr = 0;
attrlist.forkattr = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- char attrbuf[sizeof(uint32_t) + sizeof(attrreference_t) + (PATH_MAX + 1)];
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* attrlength attrref_t for the name UTF-8 name up to PATH_MAX chars */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t attrbufSize = sizeof(uint32_t) + sizeof(attrreference_t) + (PATH_MAX + 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* attrlength attrref_t for the name UTF-8 name up to PATH_MAX chars */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *attrbuf = malloc(attrbufSize);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (attrbuf == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: malloc");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span>
// FIXME This sometimes violates the stack canary
<span style='display:block; white-space:pre;background:#ffe0e0;'>- if (-1 == (getattrlist(".", &attrlist, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (-1 == (getattrlist(".", &attrlist, attrbuf, attrbufSize, FSOPT_NOFOLLOW))) {
</span> perror("darwintrace: getattrlist");
abort();
}
attrreference_t *nameAttrRef = (attrreference_t *) (attrbuf + sizeof(uint32_t));
<span style='display:block; white-space:pre;background:#ffe0e0;'>- strlcpy(normPath, ((char *) nameAttrRef) + nameAttrRef->attr_dataoffset, sizeof(normPath));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_tokenize(normPath, ((char *) nameAttrRef) + nameAttrRef->attr_dataoffset)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: path_tokenize");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span> # else /* defined(ATTR_CMN_FULLPATH) */
<span style='display:block; white-space:pre;background:#ffe0e0;'>- if (getcwd(normPath, sizeof(normPath)) == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *cwd = getcwd(NULL, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (cwd == NULL) {
</span> perror("darwintrace: getcwd");
abort();
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>-# endif /* defined(ATTR_CMN_FULLPATH) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- char *writableToken = normPath + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- while ((idx = strcspn(writableToken, "/")) > 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // found a token, tokenize and store it
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[numComponents].start = writableToken;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[numComponents].len = idx;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents++;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- bool final = writableToken[idx] == '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- writableToken[idx] = '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (final) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // advance token
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- writableToken += idx + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // copy path after the CWD into the buffer and normalize it
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (numComponents > 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- path_component_t *lastComponent = pathComponents + (numComponents - 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst = lastComponent->start + lastComponent->len + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst = normPath + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_tokenize(normPath, cwd)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: path_tokenize");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span> }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // continue parsing at the begin of path
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- token = path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(cwd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# endif /* defined(ATTR_CMN_FULLPATH) */
</span> } else {
// skip leading '/'
<span style='display:block; white-space:pre;background:#ffe0e0;'>- dst = normPath + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- *dst = '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- token = path + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ offset = 1;
</span> }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Make sure the path is normalized. NOTE: Do _not_ use realpath(3) here.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * Doing so _will_ lead to problems. This is essentially a very simple
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * re-implementation of realpath(3). */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents = __parse_path_normalize(token, dst, numComponents, pathComponents, normPath);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // strip off resource forks
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (numComponents >= 2 &&
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- strcmp("..namedfork", pathComponents[numComponents - 2].start) == 0 &&
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- strcmp("rsrc", pathComponents[numComponents - 1].start) == 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents -= 2;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *pathcopy = strdup(path + offset);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!pathcopy) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: strdup");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span> }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_tokenize(normPath, pathcopy)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: path_tokenize");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(pathcopy);
</span>
<span style='display:block; white-space:pre;background:#ffe0e0;'>-# ifdef ATTR_CMN_FULLPATH
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (numComponents >= 3 && strncmp(".vol", pathComponents[0].start, pathComponents[0].len) == 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // path in VOLFS, try to get inode -> name lookup from getattrlist(2).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // Handle resource forks (we ignore them)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_strip_resource_fork(normPath);
</span>
<span style='display:block; white-space:pre;background:#ffe0e0;'>- // Add the slashes and the terminating \0
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- for (size_t i = 0; i < numComponents; ++i) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (i == numComponents - 1) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[i].start[pathComponents[i].len] = '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[i].start[pathComponents[i].len] = '/';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- struct attrlist attrlist;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- attrlist.reserved = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- attrlist.commonattr = ATTR_CMN_FULLPATH;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- attrlist.volattr = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- attrlist.dirattr = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- attrlist.fileattr = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- attrlist.forkattr = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- char attrbuf[sizeof(uint32_t) + sizeof(attrreference_t) + (PATH_MAX + 1)];
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* attrlength attrref_t for the name UTF-8 name up to PATH_MAX chars */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (-1 == (getattrlist(normPath, &attrlist, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- perror("darwintrace: getattrlist");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // ignore and just return the /.vol/ path
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- attrreference_t *nameAttrRef = (attrreference_t *) (attrbuf + sizeof(uint32_t));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- strlcpy(normPath, ((char *) nameAttrRef) + nameAttrRef->attr_dataoffset, sizeof(normPath));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- char *writableToken = normPath + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- while ((idx = strcspn(writableToken, "/")) > 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // found a token, tokenize and store it
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[numComponents].start = writableToken;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[numComponents].len = idx;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents++;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- bool final = writableToken[idx] == '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- writableToken[idx] = '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (final) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // advance token
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- writableToken += idx + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-# endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // Handle /.vol/$devid/$inode volfs paths
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ normPath = path_resolve_volfs(normPath);
</span>
bool pathIsSymlink;
size_t loopCount = 0;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *path_native = path_str(normPath);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_native) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: path_str");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span> do {
pathIsSymlink = false;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- // Add the slashes and the terminating \0
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- for (size_t i = 0; i < numComponents; ++i) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (i == numComponents - 1) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[i].start[pathComponents[i].len] = '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathComponents[i].start[pathComponents[i].len] = '/';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span> if ((flags & DT_FOLLOWSYMS) == 0) {
// only expand symlinks when the DT_FOLLOWSYMS flags is set;
// otherwise just ignore whether this path is a symlink or not to
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -978,46 +1143,62 @@ bool __darwintrace_is_in_sandbox(const char *path, int flags) {
</span> // whether it is in the sandbox, expand it and do the same thing again.
struct stat st;
//debug_printf("checking for symlink: %s\n", normPath);
<span style='display:block; white-space:pre;background:#ffe0e0;'>- if (lstat(normPath, &st) != -1 && S_ISLNK(st.st_mode)) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (!__darwintrace_sandbox_check(normPath, flags)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (lstat(path_native, &st) != -1 && S_ISLNK(st.st_mode)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!__darwintrace_sandbox_check(path_native, flags)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path_native);
</span> return false;
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>- char link[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- pathIsSymlink = true;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- ssize_t linksize;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (-1 == (linksize = readlink(normPath, link, sizeof(link)))) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- perror("darwintrace: readlink");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t maxLinkLength = MAXPATHLEN / 2;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *link = malloc(maxLinkLength);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (link == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path_native);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: malloc");
</span> abort();
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>- link[linksize] = '\0';
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- //debug_printf("readlink(%s) = %s\n", normPath, link);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (*link == '/') {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // symlink is absolute, start fresh
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- token = link + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst = normPath + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // symlink is relative, remove last component
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- token = link;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (numComponents > 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents--;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (numComponents > 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // move dst back to the previous entry
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- path_component_t *lastComponent = pathComponents + (numComponents - 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst = lastComponent->start + lastComponent->len + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // we're at the top, move dst back to the beginning
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- dst = normPath + 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ pathIsSymlink = true;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ while (true) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ssize_t linksize;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (-1 == (linksize = readlink(path_native, link, maxLinkLength - 1))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path_native);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: readlink");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ link[linksize] = '\0';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if ((size_t) linksize < maxLinkLength - 1) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // The link did fit the buffer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ maxLinkLength += MAXPATHLEN;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *newlink = realloc(link, maxLinkLength);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!newlink) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path_native);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(link);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: realloc");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span> }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ link = newlink;
</span> }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- numComponents = __parse_path_normalize(token, dst, numComponents, pathComponents, normPath);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_tokenize_symlink(normPath, link)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: path_tokenize_symlink");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(link);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path_native);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_native = path_str(normPath);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!path_native) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ perror("darwintrace: path_str");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span> }
} while (pathIsSymlink);
<span style='display:block; white-space:pre;background:#ffe0e0;'>- return __darwintrace_sandbox_check(normPath, flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ bool result = __darwintrace_sandbox_check(path_native, flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(path_native);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ path_free(normPath);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return result;
</span> }
</pre><pre style='margin:0'>
</pre>