Commit b4940d91 authored by John Johansen's avatar John Johansen
Browse files

apparmor: in preparation for finer networking rules rework match_prot



Rework match_prot into a common fn that can be shared by all the
networking rules. This will provide compatibility with current socket
mediation, via the early bailout permission encoding.

Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent 6cc6a052
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -82,10 +82,14 @@ struct aa_secmark {

extern struct aa_sfs_entry aa_sfs_entry_network[];

/* passing in state returned by XXX_mediates(class) */
aa_state_t aa_match_to_prot(struct aa_policydb *policy, aa_state_t state,
			    u32 request, u16 family, int type, int protocol,
			    struct aa_perms **p, const char **info);
void audit_net_cb(struct audit_buffer *ab, void *va);
int aa_profile_af_perm(struct aa_profile *profile,
		       struct apparmor_audit_data *ad,
		       u32 request, u16 family, int type);
		       u32 request, u16 family, int type, int protocol);
int aa_af_perm(const struct cred *subj_cred, struct aa_label *label,
	       const char *op, u32 request, u16 family,
	       int type, int protocol);
@@ -95,7 +99,7 @@ static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
					struct sock *sk)
{
	return aa_profile_af_perm(profile, ad, request, sk->sk_family,
				  sk->sk_type);
				  sk->sk_type, sk->sk_protocol);
}
int aa_sk_perm(const char *op, u32 request, struct sock *sk);

+69 −12
Original line number Diff line number Diff line
@@ -105,16 +105,78 @@ void audit_net_cb(struct audit_buffer *ab, void *va)
	}
}

/* standard permission lookup pattern - supports early bailout */
static int do_perms(struct aa_profile *profile, struct aa_policydb *policy,
		    unsigned int state, u32 request,
		    struct aa_perms *p, struct apparmor_audit_data *ad)
{
	struct aa_perms perms;

	AA_BUG(!profile);
	AA_BUG(!policy);


	if (state || !p)
		p = aa_lookup_perms(policy, state);
	perms = *p;
	aa_apply_modes_to_perms(profile, &perms);
	return aa_check_perms(profile, &perms, request, ad,
			      audit_net_cb);
}

/* only continue match if
 *   insufficient current perms at current state
 *   indicates there are more perms in later state
 * Returns: perms struct if early match
 */
static struct aa_perms *early_match(struct aa_policydb *policy,
				    aa_state_t state, u32 request)
{
	struct aa_perms *p;

	p = aa_lookup_perms(policy, state);
	if (((p->allow & request) != request) && (p->allow & AA_CONT_MATCH))
		return NULL;
	return p;
}

/* passing in state returned by PROFILE_MEDIATES_AF */
aa_state_t aa_match_to_prot(struct aa_policydb *policy, aa_state_t state,
			    u32 request, u16 family, int type, int protocol,
			    struct aa_perms **p, const char **info)
{
	__be16 buffer;

	buffer = cpu_to_be16(family);
	state = aa_dfa_match_len(policy->dfa, state, (char *) &buffer, 2);
	if (!state) {
		*info = "failed af match";
		return DFA_NOMATCH;
	}
	buffer = cpu_to_be16((u16)type);
	state = aa_dfa_match_len(policy->dfa, state, (char *) &buffer, 2);
	if (!state)
		*info = "failed type match";
	*p = early_match(policy, state, request);
	if (!*p) {
		buffer = cpu_to_be16((u16)protocol);
		state = aa_dfa_match_len(policy->dfa, state, (char *) &buffer,
					 2);
		if (!state)
			*info = "failed protocol match";
	}
	return state;
}

/* Generic af perm */
int aa_profile_af_perm(struct aa_profile *profile,
		       struct apparmor_audit_data *ad, u32 request, u16 family,
		       int type)
		       int type, int protocol)
{
	struct aa_ruleset *rules = list_first_entry(&profile->rules,
						    typeof(*rules), list);
	struct aa_perms perms = { };
	struct aa_perms *p = NULL;
	aa_state_t state;
	__be16 buffer[2];

	AA_BUG(family >= AF_MAX);
	AA_BUG(type < 0 || type >= SOCK_MAX);
@@ -124,14 +186,9 @@ int aa_profile_af_perm(struct aa_profile *profile,
	if (!state)
		return 0;

	buffer[0] = cpu_to_be16(family);
	buffer[1] = cpu_to_be16((u16) type);
	state = aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer,
				 4);
	perms = *aa_lookup_perms(rules->policy, state);
	aa_apply_modes_to_perms(profile, &perms);

	return aa_check_perms(profile, &perms, request, ad, audit_net_cb);
	state = aa_match_to_prot(rules->policy, state, request, family, type,
				 protocol, &p, &ad->info);
	return do_perms(profile, rules->policy, state, request, p, ad);
}

int aa_af_perm(const struct cred *subj_cred, struct aa_label *label,
@@ -142,7 +199,7 @@ int aa_af_perm(const struct cred *subj_cred, struct aa_label *label,

	return fn_for_each_confined(label, profile,
			aa_profile_af_perm(profile, &ad, request, family,
					   type));
					   type, protocol));
}

static int aa_label_sk_perm(const struct cred *subj_cred,