Пример #1
0
static int init(struct selabel_handle *rec, struct selinux_opt *opts,
		unsigned n)
{
	struct saved_data *data = (struct saved_data *)rec->data;
	const char *path = NULL;
	FILE *fp;
	char line_buf[BUFSIZ];
	unsigned int lineno = 0, maxnspec, pass;
	int status = -1;
	struct stat sb;

	/* Process arguments */
	while (n--)
		switch (opts[n].type) {
		case SELABEL_OPT_PATH:
			path = opts[n].value;
			break;
		}

	if (!path) 
		return -1;

	/* Open the specification file. */
	if ((fp = fopen(path, "r")) == NULL)
		return -1;

	if (fstat(fileno(fp), &sb) < 0)
		goto finish;
	errno = EINVAL;
	if (!S_ISREG(sb.st_mode))
		goto finish;

	/*
	 * Two passes of the specification file. First is to get the size.
	 * After the first pass, the spec array is malloced to the appropriate 
	 * size. Second pass is to populate the spec array and check for 
	 * dups.
	 */
	maxnspec = UINT_MAX / sizeof(spec_t);
	for (pass = 0; pass < 2; pass++) {
		data->nspec = 0;

		while (fgets(line_buf, sizeof line_buf - 1, fp)
		       && data->nspec < maxnspec) {
			if (process_line(rec, path, line_buf, pass, ++lineno) != 0)
				goto finish;
		}

		if (pass == 1) {
			status = nodups_specs(data, path);

			if (status)
				goto finish;
		}

		if (pass == 0) {

			if (data->nspec == 0) {
				status = 0;
				goto finish;
			}

			if (NULL == (data->spec_arr =
				     malloc(sizeof(spec_t) * data->nspec)))
				goto finish;

			memset(data->spec_arr, 0, sizeof(spec_t) * data->nspec);
			maxnspec = data->nspec;
			rewind(fp);
		}
	}

	qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp);

	status = 0;
finish:
	fclose(fp);
	return status;
}
Пример #2
0
static int init(struct selabel_handle *rec, struct selinux_opt *opts,
                unsigned n)
{
    struct saved_data *data = (struct saved_data *)rec->data;
    const char *path = NULL;
    const char *prefix = NULL;
    FILE *fp;
    FILE *localfp = NULL;
    FILE *homedirfp = NULL;
    char local_path[PATH_MAX + 1];
    char homedir_path[PATH_MAX + 1];
    char *line_buf = NULL;
    size_t line_len = 0;
    unsigned int lineno, pass, i, j, maxnspec;
    spec_t *spec_copy = NULL;
    int status = -1, baseonly = 0;
    struct stat sb;

    /* Process arguments */
    while (n--)
        switch(opts[n].type) {
        case SELABEL_OPT_PATH:
            path = opts[n].value;
            break;
        case SELABEL_OPT_SUBSET:
            prefix = opts[n].value;
            break;
        case SELABEL_OPT_BASEONLY:
            baseonly = !!opts[n].value;
            break;
        }

    /* Open the specification file. */
    if (!path)
        path = selinux_file_context_path();
    if ((fp = fopen(path, "r")) == NULL)
        return -1;
    __fsetlocking(fp, FSETLOCKING_BYCALLER);

    if (fstat(fileno(fp), &sb) < 0)
        return -1;
    if (!S_ISREG(sb.st_mode)) {
        errno = EINVAL;
        return -1;
    }

    if (!baseonly) {
        snprintf(homedir_path, sizeof(homedir_path), "%s.homedirs",
                 path);
        homedirfp = fopen(homedir_path, "r");
        if (homedirfp != NULL)
            __fsetlocking(homedirfp, FSETLOCKING_BYCALLER);

        snprintf(local_path, sizeof(local_path), "%s.local", path);
        localfp = fopen(local_path, "r");
        if (localfp != NULL)
            __fsetlocking(localfp, FSETLOCKING_BYCALLER);
    }

    /*
     * Perform two passes over the specification file.
     * The first pass counts the number of specifications and
     * performs simple validation of the input.  At the end
     * of the first pass, the spec array is allocated.
     * The second pass performs detailed validation of the input
     * and fills in the spec array.
     */
    maxnspec = UINT_MAX / sizeof(spec_t);
    for (pass = 0; pass < 2; pass++) {
        lineno = 0;
        data->nspec = 0;
        data->ncomp = 0;
        while (getline(&line_buf, &line_len, fp) > 0
                && data->nspec < maxnspec) {
            if (process_line(rec, path, prefix, line_buf,
                             pass, ++lineno) != 0)
                goto finish;
        }
        if (pass == 1) {
            status = nodups_specs(data, path);
            if (status)
                goto finish;
        }
        lineno = 0;
        if (homedirfp)
            while (getline(&line_buf, &line_len, homedirfp) > 0
                    && data->nspec < maxnspec) {
                if (process_line
                        (rec, homedir_path, prefix,
                         line_buf, pass, ++lineno) != 0)
                    goto finish;
            }

        lineno = 0;
        if (localfp)
            while (getline(&line_buf, &line_len, localfp) > 0
                    && data->nspec < maxnspec) {
                if (process_line
                        (rec, local_path, prefix, line_buf,
                         pass, ++lineno) != 0)
                    goto finish;
            }

        if (pass == 0) {
            if (data->nspec == 0) {
                status = 0;
                goto finish;
            }
            if (NULL == (data->spec_arr =
                             malloc(sizeof(spec_t) * data->nspec)))
                goto finish;
            memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec);
            maxnspec = data->nspec;
            rewind(fp);
            if (homedirfp)
                rewind(homedirfp);
            if (localfp)
                rewind(localfp);
        }
    }
    free(line_buf);

    /* Move exact pathname specifications to the end. */
    spec_copy = malloc(sizeof(spec_t) * data->nspec);
    if (!spec_copy)
        goto finish;
    j = 0;
    for (i = 0; i < data->nspec; i++)
        if (data->spec_arr[i].hasMetaChars)
            memcpy(&spec_copy[j++],
                   &data->spec_arr[i], sizeof(spec_t));
    for (i = 0; i < data->nspec; i++)
        if (!data->spec_arr[i].hasMetaChars)
            memcpy(&spec_copy[j++],
                   &data->spec_arr[i], sizeof(spec_t));
    free(data->spec_arr);
    data->spec_arr = spec_copy;

    status = 0;
finish:
    fclose(fp);
    if (data->spec_arr != spec_copy)
        free(data->spec_arr);
    if (homedirfp)
        fclose(homedirfp);
    if (localfp)
        fclose(localfp);
    return status;
}
Пример #3
0
static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
		unsigned n)
{
	struct saved_data *data = (struct saved_data *)rec->data;
	const char *path = NULL;
	const char *prefix = NULL;
	char subs_file[PATH_MAX + 1];
	int status = -1, baseonly = 0;

	/* Process arguments */
	while (n--)
		switch(opts[n].type) {
		case SELABEL_OPT_PATH:
			path = opts[n].value;
			break;
		case SELABEL_OPT_SUBSET:
			prefix = opts[n].value;
			break;
		case SELABEL_OPT_BASEONLY:
			baseonly = !!opts[n].value;
			break;
		}

	/* Process local and distribution substitution files */
	if (!path) {
		rec->dist_subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->dist_subs);
		rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
		path = selinux_file_context_path();
	} else {
		snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path);
		rec->dist_subs = selabel_subs_init(subs_file, rec->dist_subs);
		snprintf(subs_file, sizeof(subs_file), "%s.subs", path);
		rec->subs = selabel_subs_init(subs_file, rec->subs);
	}

	rec->spec_file = strdup(path);

	/*
	 * The do detailed validation of the input and fill the spec array
	 */
	status = process_file(path, NULL, rec, prefix);
	if (status)
		goto finish;

	if (rec->validating) {
		status = nodups_specs(data, path);
		if (status)
			goto finish;
	}

	if (!baseonly) {
		status = process_file(path, "homedirs", rec, prefix);
		if (status && errno != ENOENT)
			goto finish;

		status = process_file(path, "local", rec, prefix);
		if (status && errno != ENOENT)
			goto finish;
	}

	status = sort_specs(data);

finish:
	if (status)
		free(data->spec_arr);
	return status;
}