예제 #1
0
파일: mount.c 프로젝트: Lyude/linux
static int profile_umount(struct aa_profile *profile, struct path *path,
			  char *buffer)
{
	struct aa_perms perms = { };
	const char *name = NULL, *info = NULL;
	unsigned int state;
	int error;

	AA_BUG(!profile);
	AA_BUG(!path);

	if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
		return 0;

	error = aa_path_name(path, path_flags(profile, path), buffer, &name,
			     &info, profile->disconnected);
	if (error)
		goto audit;

	state = aa_dfa_match(profile->policy.dfa,
			     profile->policy.start[AA_CLASS_MOUNT],
			     name);
	perms = compute_mnt_perms(profile->policy.dfa, state);
	if (AA_MAY_UMOUNT & ~perms.allow)
		error = -EACCES;

audit:
	return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
			   AA_MAY_UMOUNT, &perms, info, error);
}
예제 #2
0
파일: ipc.c 프로젝트: SelfImp/m75
/* TODO: update to handle compound name&name2, conditionals */
static void profile_match_signal(struct aa_profile *profile, const char *label,
				 int signal, struct aa_perms *perms)
{
	unsigned int state;
	if (profile->policy.dfa) {
		/* TODO: secondary cache check <profile, profile, perm> */
		state = aa_dfa_next(profile->policy.dfa,
				    profile->policy.start[AA_CLASS_SIGNAL],
				    signal);
		state = aa_dfa_match(profile->policy.dfa, state, label);
		aa_compute_perms(profile->policy.dfa, state, perms);
	} else
		memset(perms, 0, sizeof(*perms));
}
예제 #3
0
파일: lib.c 프로젝트: SelfImp/m75
void aa_profile_match_label(struct aa_profile *profile, const char *label,
			    int type, struct aa_perms *perms)
{
	/* TODO: doesn't yet handle extended types */
	unsigned int state;
	if (profile->policy.dfa) {
		state = aa_dfa_next(profile->policy.dfa,
				    profile->policy.start[AA_CLASS_LABEL],
				    type);
		state = aa_dfa_match(profile->policy.dfa, state, label);
		aa_compute_perms(profile->policy.dfa, state, perms);
	} else
		memset(perms, 0, sizeof(*perms));
}
예제 #4
0
static unsigned int leftmatch_fb(struct aa_dfa *dfa, unsigned int start,
				 const char *str, struct match_workbuf *wb,
				 unsigned int *count)
{
	u16 *def = DEFAULT_TABLE(dfa);
	u32 *base = BASE_TABLE(dfa);
	u16 *next = NEXT_TABLE(dfa);
	u16 *check = CHECK_TABLE(dfa);
	unsigned int state = start, pos;

	AA_BUG(!dfa);
	AA_BUG(!str);
	AA_BUG(!wb);
	AA_BUG(!count);

	*count = 0;
	if (state == 0)
		return 0;

	/* current state is <state>, matching character *str */
	if (dfa->tables[YYTD_ID_EC]) {
		/* Equivalence class table defined */
		u8 *equiv = EQUIV_TABLE(dfa);
		/* default is direct to next state */
		while (*str) {
			unsigned int adjust;

			wb->history[wb->pos] = state;
			pos = base_idx(base[state]) + equiv[(u8) *str++];
			if (check[pos] == state)
				state = next[pos];
			else
				state = def[state];
			if (is_loop(wb, state, &adjust)) {
				state = aa_dfa_match(dfa, state, str);
				*count -= adjust;
				goto out;
			}
			inc_wb_pos(wb);
			(*count)++;
		}
	} else {
		/* default is direct to next state */
		while (*str) {
			unsigned int adjust;

			wb->history[wb->pos] = state;
			pos = base_idx(base[state]) + (u8) *str++;
			if (check[pos] == state)
				state = next[pos];
			else
				state = def[state];
			if (is_loop(wb, state, &adjust)) {
				state = aa_dfa_match(dfa, state, str);
				*count -= adjust;
				goto out;
			}
			inc_wb_pos(wb);
			(*count)++;
		}
	}

out:
	if (!state)
		*count = 0;
	return state;
}
예제 #5
0
파일: mount.c 프로젝트: Lyude/linux
int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
{
	struct aa_profile *profile;
	char *buffer = NULL;
	int error;
	struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };

	AA_BUG(!label);
	AA_BUG(!mnt);

	get_buffers(buffer);
	error = fn_for_each_confined(label, profile,
			profile_umount(profile, &path, buffer));
	put_buffers(buffer);

	return error;
}

/* helper fn for transition on pivotroot
 *
 * Returns: label for transition or ERR_PTR. Does not return NULL
 */
static struct aa_label *build_pivotroot(struct aa_profile *profile,
					const struct path *new_path,
					char *new_buffer,
					const struct path *old_path,
					char *old_buffer)
{
	const char *old_name, *new_name = NULL, *info = NULL;
	const char *trans_name = NULL;
	struct aa_perms perms = { };
	unsigned int state;
	int error;

	AA_BUG(!profile);
	AA_BUG(!new_path);
	AA_BUG(!old_path);

	if (profile_unconfined(profile) ||
	    !PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
		return aa_get_newest_label(&profile->label);

	error = aa_path_name(old_path, path_flags(profile, old_path),
			     old_buffer, &old_name, &info,
			     profile->disconnected);
	if (error)
		goto audit;
	error = aa_path_name(new_path, path_flags(profile, new_path),
			     new_buffer, &new_name, &info,
			     profile->disconnected);
	if (error)
		goto audit;

	error = -EACCES;
	state = aa_dfa_match(profile->policy.dfa,
			     profile->policy.start[AA_CLASS_MOUNT],
			     new_name);
	state = aa_dfa_null_transition(profile->policy.dfa, state);
	state = aa_dfa_match(profile->policy.dfa, state, old_name);
	perms = compute_mnt_perms(profile->policy.dfa, state);

	if (AA_MAY_PIVOTROOT & perms.allow)
		error = 0;

audit:
	error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
			    NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
			    &perms, info, error);
	if (error)
		return ERR_PTR(error);

	return aa_get_newest_label(&profile->label);
}

int aa_pivotroot(struct aa_label *label, const struct path *old_path,
		 const struct path *new_path)
{
	struct aa_profile *profile;
	struct aa_label *target = NULL;
	char *old_buffer = NULL, *new_buffer = NULL, *info = NULL;
	int error;

	AA_BUG(!label);
	AA_BUG(!old_path);
	AA_BUG(!new_path);

	get_buffers(old_buffer, new_buffer);
	target = fn_label_build(label, profile, GFP_ATOMIC,
			build_pivotroot(profile, new_path, new_buffer,
					old_path, old_buffer));
	if (!target) {
		info = "label build failed";
		error = -ENOMEM;
		goto fail;
	} else if (!IS_ERR(target)) {
		error = aa_replace_current_label(target);
		if (error) {
			/* TODO: audit target */
			aa_put_label(target);
			goto out;
		}
	} else
		/* already audited error */
		error = PTR_ERR(target);
out:
	put_buffers(old_buffer, new_buffer);

	return error;

fail:
	/* TODO: add back in auditing of new_name and old_name */
	error = fn_for_each(label, profile,
			audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */,
				    NULL /* old_name */,
				    NULL, NULL,
				    0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
				    error));
	goto out;
}
예제 #6
0
파일: mount.c 프로젝트: Lyude/linux
/**
 * compute_mnt_perms - compute mount permission associated with @state
 * @dfa: dfa to match against (NOT NULL)
 * @state: state match finished in
 *
 * Returns: mount permissions
 */
static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa,
					   unsigned int state)
{
	struct aa_perms perms = {
		.allow = dfa_user_allow(dfa, state),
		.audit = dfa_user_audit(dfa, state),
		.quiet = dfa_user_quiet(dfa, state),
		.xindex = dfa_user_xindex(dfa, state),
	};

	return perms;
}

static const char * const mnt_info_table[] = {
	"match succeeded",
	"failed mntpnt match",
	"failed srcname match",
	"failed type match",
	"failed flags match",
	"failed data match"
};

/*
 * Returns 0 on success else element that match failed in, this is the
 * index into the mnt_info_table above
 */
static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
			const char *mntpnt, const char *devname,
			const char *type, unsigned long flags,
			void *data, bool binary, struct aa_perms *perms)
{
	unsigned int state;

	AA_BUG(!dfa);
	AA_BUG(!perms);

	state = aa_dfa_match(dfa, start, mntpnt);
	state = aa_dfa_null_transition(dfa, state);
	if (!state)
		return 1;

	if (devname)
		state = aa_dfa_match(dfa, state, devname);
	state = aa_dfa_null_transition(dfa, state);
	if (!state)
		return 2;

	if (type)
		state = aa_dfa_match(dfa, state, type);
	state = aa_dfa_null_transition(dfa, state);
	if (!state)
		return 3;

	state = match_mnt_flags(dfa, state, flags);
	if (!state)
		return 4;
	*perms = compute_mnt_perms(dfa, state);
	if (perms->allow & AA_MAY_MOUNT)
		return 0;

	/* only match data if not binary and the DFA flags data is expected */
	if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
		state = aa_dfa_null_transition(dfa, state);
		if (!state)
			return 4;

		state = aa_dfa_match(dfa, state, data);
		if (!state)
			return 5;
		*perms = compute_mnt_perms(dfa, state);
		if (perms->allow & AA_MAY_MOUNT)
			return 0;
	}

	/* failed at end of flags match */
	return 4;
}