Exemplo n.º 1
0
bool strlist_cmp(strlist *a, strlist *b)
{
    if (a->count != b->count) return false;

    for (unsigned i = 0; i < a->count; ++i)
	if (0 != strcmp(strlist_get(a, i), strlist_get(b, i)))
	    return false;
    return true;
}
Exemplo n.º 2
0
char *strlist2char(strlist *list)
{
    char *data = strlist_get(list, 0);

    data = strcat_static(encodeStr(data), "");
    for (unsigned i = 1; i < list->count; ++i) {
	data = strcat_static(data, " ");
	data = strcat_static(data, encodeStr(strlist_get(list, i)));
    }
    return data;
}
Exemplo n.º 3
0
static void
execCmdline(strlist_t *cmdline, strlist_t *env, const char *workdir)
{
    custr_t *execname;

    execname = execName(strlist_get(cmdline, 0), env, workdir);
    dlog("EXECNAME \"%s\"\n", custr_cstr(execname));

    /*
     * We need to drop privs *after* we've setup /dev/zfd/[0-2] since that
     * requires being root.
     */
    dlog("DROP PRIVS\n");

    if (grp != NULL) {
        if (setgid(grp->gr_gid) != 0) {
            fatal(ERR_SETGID, "setgid(%d): %s\n", grp->gr_gid, strerror(errno));
        }
    }
    if (pwd != NULL) {
        if (initgroups(pwd->pw_name, grp->gr_gid) != 0) {
            fatal(ERR_INITGROUPS, "initgroups(%s,%d): %s\n", pwd->pw_name,
                  grp->gr_gid, strerror(errno));
        }
        if (setuid(pwd->pw_uid) != 0) {
            fatal(ERR_SETUID, "setuid(%d): %s\n", pwd->pw_uid, strerror(errno));
        }
    }

    execve(custr_cstr(execname), strlist_array(cmdline), strlist_array(env));

    fatal(ERR_EXEC_FAILED, "execve(%s) failed: %s\n", execname,
          strerror(errno));
}
Exemplo n.º 4
0
bool record_create(record_t *record, const char *prog, int argc, char **argv)
{
    char hash_buf[SHA1_STRING_LEN];
    const char *prog_bin = prog;
    unsigned i;

    record_clear(record);

    if (strrchr(prog, '/'))
	prog_bin = strrchr(prog, '/') + 1;

    if (!sha1_file(prog, hash_buf)) return false;
    strlist_push_back(&record->prog_line, prog_bin);
    strlist_push_back(&record->prog_line, sha1_file(prog, hash_buf));
    for (i = 0; i < (unsigned)argc; ++i)
	strlist_push_back(&record->prog_line, argv[i]);

    strlist lib_list = STRLIST_INITIALIZER;
    get_libs(&lib_list, prog);
    for (i = 0; i < lib_list.count; ++i) {
	const char *lib_path = strlist_get(&lib_list, i);

	if (!sha1_file(lib_path, hash_buf)) continue;
	strlist_push_back(&record->lib_line, lib_path);
	strlist_push_back(&record->lib_line, sha1_file(lib_path, hash_buf));
    }

    record->enabled = true;
    return true;
}
Exemplo n.º 5
0
strlist libs_diff(strlist *prev_run, strlist *curr_run)
{
    strlist result = STRLIST_INITIALIZER;
    char buf[STRING_MAX];

    unsigned prev_cnt = 0, curr_cnt = 0;
    char *prev_ptr = strlist_get(prev_run, prev_cnt);
    char *curr_ptr = strlist_get(curr_run, curr_cnt);
    int retval = 0;

    while (prev_ptr || curr_ptr) {
	if (prev_ptr && curr_ptr) {
	    retval = strcmp(prev_ptr, curr_ptr);

	    if (retval == 0) {
		// Libraries match.  Compare file contents.
		char *prev_hash = strlist_get(prev_run, ++prev_cnt);
		char *curr_hash = strlist_get(curr_run, ++curr_cnt);

		if (strcmp(prev_hash, curr_hash) != 0) {
		    snprintf(buf, sizeof(buf), "* %s has changed since last run.", prev_ptr);
		    strlist_push_back(&result, buf);
		}

		prev_ptr = strlist_get(prev_run, ++prev_cnt);
		curr_ptr = strlist_get(curr_run, ++curr_cnt);
		continue;
	    }
	}

	if (!curr_ptr || retval < 0) {
	    // If (there are no more libraries from `ldd`) OR
	    //    (library from history record not found in `ldd` list)

	    snprintf(buf, sizeof(buf), "* Mutatee is no longer dependent on %s.", prev_ptr);
	    strlist_push_back(&result, buf);

	    ++prev_cnt; // Skip digest string.
	    prev_ptr = strlist_get(prev_run, ++prev_cnt);

	} else if (!prev_ptr || retval > 0) {
	    // If (there are no more libraries from the history record) OR
	    //    (library from `ldd` not found in history record list)

	    snprintf(buf, sizeof(buf), "* Mutatee is now dependent on %s.", curr_ptr);
	    strlist_push_back(&result, buf);

	    ++curr_cnt; // Skip digest string.
	    curr_ptr = strlist_get(curr_run, ++curr_cnt);
	}
    }
    return result;
}
Exemplo n.º 6
0
void record_update(record_t *newRecord)
{
    FILE *index_fd;
    FILE *new_fd;
    char index_filename[PATH_MAX];
    char new_index_filename[PATH_MAX];

    strncpy(index_filename, config.record_dir, sizeof(index_filename));
    strncat(index_filename, "/", sizeof(index_filename) - strlen(index_filename));
    strncat(index_filename, HISTORY_RECORD_INDEX_FILE, sizeof(index_filename) - strlen(index_filename));
    errno = 0;
    index_fd = fopen(index_filename, "r");
    if (!index_fd) {
	fprintf(stderr, "Could not open %s\n", index_filename);
	return;
    }

    strncpy(new_index_filename, index_filename, sizeof(new_index_filename));
    strncat(new_index_filename, ".update", sizeof(new_index_filename) - strlen(new_index_filename));
    new_fd = fopen(new_index_filename, "w");
    if (!new_fd) {
	fprintf(stderr, "Could not open %s\n", new_index_filename);
	return;
    }

    char *buf = NULL;
    bool found = false;
    strlist prog_line = STRLIST_INITIALIZER;
    while ( (buf = fgets_static(index_fd))) {
	chomp(buf);

	if (buf[0] == '\t' || buf[0] == '\0') {
	    fprintf(new_fd, "%s\n", buf);
	    buf[0] = '\0';
	    continue;
	}

	prog_line = char2strlist(buf);
	if (strlist_cmp(&prog_line, &newRecord->prog_line)) {
	    fprintf(new_fd, "%s\n", buf);

	    strlist_push_front(&newRecord->lib_line, newRecord->filename);
	    buf = strlist2char(&newRecord->lib_line);
	    fprintf(new_fd, "\t%s\n", buf);
	    strlist_pop_front(&newRecord->lib_line);

	    while ( (buf = fgets_static(index_fd)) && buf[0] == '\t') {
		chomp(buf);

		strlist lib_line = char2strlist(buf);
		strlist_pop_front(&lib_line);

		if (!strlist_cmp(&lib_line, &newRecord->lib_line))
		    fprintf(new_fd, "%s\n", buf);

		strlist_clear(&lib_line);
	    }
	    fprintf(new_fd, "%s", buf);  // NOTE: Do not print "%s\n" here.

	    found = true;
	    break;
	}

	if (strcmp(strlist_get(&newRecord->prog_line, 0),
		   strlist_get(&prog_line, 0)) < 0)
	    break;

	strlist_clear(&prog_line);
	fprintf(new_fd, "%s\n", buf);
	buf[0] = '\0';
    }

    // New binary signature entry.
    if (!found) {
	char *buf2;

	buf2 = strlist2char(&newRecord->prog_line);
	fprintf(new_fd, "%s\n", buf2);

	strlist_push_front(&newRecord->lib_line, newRecord->filename);
	buf2 = strlist2char(&newRecord->lib_line);
	fprintf(new_fd, "\t%s\n\n", buf2);
	strlist_pop_front(&newRecord->lib_line);

	if (buf && buf[0] != '\0')
	    fprintf(new_fd, "%s\n", buf);
    }

    while ( (buf = fgets_static(index_fd)))
	fprintf(new_fd, "%s", buf);  // NOTE: Do not print "%s\n" here.

    fclose(index_fd);
    fclose(new_fd);

    unlink(index_filename);
    rename(new_index_filename, index_filename);
}
Exemplo n.º 7
0
bool record_search(record_t *newRecord)
{
    FILE *index_fd;
    char *index_filename;
    bool found = false, latest = true;

    index_filename = sprintf_static("%s/%s", config.record_dir, HISTORY_RECORD_INDEX_FILE);
    errno = 0;
    index_fd = fopen(index_filename, "r");

    if (errno && errno == ENOENT) {
	index_fd = fopen(index_filename, "w");
	if (!index_fd) {
	    fprintf(config.outfd, "*\n* Error opening history record index %s.  Disabling history record.\n*\n", index_filename);
	    newRecord->enabled = false;
	    return false;
	}
	fclose(index_fd);

    } else if (!index_fd) {
	fprintf(config.outfd, "*\n* Error opening history record index %s.  Disabling history record.\n*\n", index_filename);
        newRecord->enabled = false;
	return false;

    } else {
	// We should use C++ string instead to avoid buffer overflows.
	char *buf;
	while ( (buf = fgets_static(index_fd))) {
	    if (buf[0] == '\t' || buf[0] == '\n') continue;

	    chomp(buf);
	    strlist prog_line = char2strlist(buf);
	    if (strlist_cmp(&prog_line, &newRecord->prog_line)) {

		strlist diff_list = STRLIST_INITIALIZER;
		while (!found && (buf = fgets_static(index_fd)) && buf[0] == '\t') {
		    chomp(buf);
		    strlist lib_line = char2strlist(buf + 1);

		    strncpy(newRecord->filename, strlist_get(&lib_line, 0), sizeof(newRecord->filename));
		    strlist_pop_front(&lib_line);

		    if (strlist_cmp(&lib_line, &newRecord->lib_line)) {
			found = true;

		    } else {
			if (latest)
			    diff_list = libs_diff(&lib_line, &newRecord->lib_line);
			latest = false;
		    }
		    strlist_clear(&lib_line);
		}

		if (!found) {
		    fprintf(config.outfd, "* Warning: Current library set unknown.  Differences from latest run include:\n");
		    fprintf(config.outfd, "*\n");
		    for (unsigned i = 0; i < diff_list.count; ++i)
			fprintf(config.outfd, "%s\n", strlist_get(&diff_list, i));

		} else if (!latest)
		    fprintf(config.outfd, "* Warning: Current library signature does not match latest run.\n");

		strlist_clear(&diff_list);
	    }
	    strlist_clear(&prog_line);
	}
	fclose(index_fd);
    }

    if (!found) {
	// Fill storage file information
	const char *prog_file = strlist_get(&newRecord->prog_line, 0);
	if (strrchr(prog_file, '/'))
	    prog_file = strrchr(prog_file, '/') + 1;

	snprintf(newRecord->filename, sizeof(newRecord->filename), "%s/%s-XXXXXX", config.record_dir, prog_file);
	int file_desc = mkstemp(newRecord->filename);
	newRecord->fd = fdopen(file_desc, "a");

    } else {
	newRecord->fd = fopen(newRecord->filename, "a");
    }

    char timestr[STRING_MAX];
    time_t timestamp = time(NULL);

    strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %Z", localtime(&timestamp));
    fprintf(newRecord->fd, "Log start: %s\n", timestr);
    fprintf(newRecord->fd, "--------------------------------------------------------------------------------\n");

    char raw_filename[ PATH_MAX ];
    strncpy(raw_filename, newRecord->filename, sizeof(raw_filename));
    strncat(raw_filename, ".raw", sizeof(raw_filename) - strlen(raw_filename));
    newRecord->raw_fd = fopen(raw_filename, "a");

    fprintf(newRecord->raw_fd, "Raw transcript log start: %s\n", timestr);
    fprintf(newRecord->raw_fd, "--------------------------------------------------------------------------------\n");

    return (found && latest);
}