static int allowed_match(const char* path, const char* okpath, const char *denypath, int debug) { char resolvedBuf[PATH_MAX]; const char* resolved = path; if (!strncmp(resolved, "/proc/self", 10)) { // Leave references to /proc/self.* alone as its real path is different // each time. } else { resolved = realpath(path, resolvedBuf); if (resolved == NULL) { return 0; } } while (*denypath) { const char* end = my_strchrnul(denypath, ':'); if (strncmp(denypath, resolved, end - denypath) == 0) goto deny; denypath = end; while (*denypath == ':') ++denypath; } while (*okpath) { const char* end = my_strchrnul(okpath, ':'); if (strncmp(okpath, resolved, end - okpath) == 0) return 1; okpath = end; while (*okpath == ':') ++okpath; } deny: if (debug) { fprintf(stderr, "Access to \"%s\" denied by gcc-explorer policy\n", path); } errno = EACCES; return 0; }
size_t my_strcspn(const char *s, const char *c) { const char *a = s; size_t byteset[32/sizeof(size_t)]; if (!c[0] || !c[1]) return my_strchrnul(s, *c)-a; my_memset(byteset, 0, sizeof byteset); for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++); for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++); return s-a; }
/* Based on g_find_program_in_path, stolen from glib/gutils.c * It allow to ask in a specific PATH, if fail then as in the user PATH with * EXTRA_PATH appended. */ gchar * util_find_program_in_path (const gchar * program, const gchar * path) { const gchar *p; gchar *name, *freeme, *user_path = NULL; size_t len; size_t pathlen; g_return_val_if_fail (program != NULL, NULL); /* If it is an absolute path, or a relative path including subdirectories, * don't look in PATH. */ if (g_path_is_absolute (program) || strchr (program, G_DIR_SEPARATOR) != NULL) { if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE)) return g_strdup (program); else return NULL; } if (path == NULL) { path = g_getenv ("PATH"); if (path == NULL) { path = "/bin:/usr/bin:."; } /* /sbin and /usr/sbin might not be in the user's path */ user_path = g_strconcat (path, ":", EXTRA_PATH, NULL); path = user_path; } len = strlen (program) + 1; pathlen = strlen (path); freeme = name = g_malloc (pathlen + len + 1); /* Copy the file name at the top, including '\0' */ memcpy (name + pathlen + 1, program, len); name = name + pathlen; /* And add the slash before the filename */ *name = G_DIR_SEPARATOR; p = path; do { char *startp; path = p; p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR); if (p == path) /* Two adjacent colons, or a colon at the beginning or the end * of `PATH' means to search the current directory. */ startp = name + 1; else startp = memcpy (name - (p - path), path, p - path); if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE)) { gchar *ret; ret = g_strdup (startp); g_free (freeme); g_free (user_path); return ret; } } while (*p++ != '\0'); g_free (freeme); g_free (user_path); return NULL; }