Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

apparmor: add gerneric permissions struct and support fns

parent b5b2557c
Loading
Loading
Loading
Loading
+15 −15
Original line number Diff line number Diff line
@@ -56,15 +56,15 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
	struct common_audit_data *sa = va;
	kuid_t fsuid = current_fsuid();

	if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
	if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
		audit_log_format(ab, " requested_mask=");
		audit_file_mask(ab, aad(sa)->fs.request);
		audit_file_mask(ab, aad(sa)->request);
	}
	if (aad(sa)->fs.denied & AA_AUDIT_FILE_MASK) {
	if (aad(sa)->denied & AA_AUDIT_FILE_MASK) {
		audit_log_format(ab, " denied_mask=");
		audit_file_mask(ab, aad(sa)->fs.denied);
		audit_file_mask(ab, aad(sa)->denied);
	}
	if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
	if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
		audit_log_format(ab, " fsuid=%d",
				 from_kuid(&init_user_ns, fsuid));
		audit_log_format(ab, " ouid=%d",
@@ -100,7 +100,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op);

	sa.u.tsk = NULL;
	aad(&sa)->fs.request = request;
	aad(&sa)->request = request;
	aad(&sa)->name = name;
	aad(&sa)->fs.target = target;
	aad(&sa)->fs.ouid = ouid;
@@ -115,30 +115,30 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
			mask = 0xffff;

		/* mask off perms that are not being force audited */
		aad(&sa)->fs.request &= mask;
		aad(&sa)->request &= mask;

		if (likely(!aad(&sa)->fs.request))
		if (likely(!aad(&sa)->request))
			return 0;
		type = AUDIT_APPARMOR_AUDIT;
	} else {
		/* only report permissions that were denied */
		aad(&sa)->fs.request = aad(&sa)->fs.request & ~perms->allow;
		AA_BUG(!aad(&sa)->fs.request);
		aad(&sa)->request = aad(&sa)->request & ~perms->allow;
		AA_BUG(!aad(&sa)->request);

		if (aad(&sa)->fs.request & perms->kill)
		if (aad(&sa)->request & perms->kill)
			type = AUDIT_APPARMOR_KILL;

		/* quiet known rejects, assumes quiet and kill do not overlap */
		if ((aad(&sa)->fs.request & perms->quiet) &&
		if ((aad(&sa)->request & perms->quiet) &&
		    AUDIT_MODE(profile) != AUDIT_NOQUIET &&
		    AUDIT_MODE(profile) != AUDIT_ALL)
			aad(&sa)->fs.request &= ~perms->quiet;
			aad(&sa)->request &= ~perms->quiet;

		if (!aad(&sa)->fs.request)
		if (!aad(&sa)->request)
			return COMPLAIN_MODE(profile) ? 0 : aad(&sa)->error;
	}

	aad(&sa)->fs.denied = aad(&sa)->fs.request & ~perms->allow;
	aad(&sa)->denied = aad(&sa)->request & ~perms->allow;
	return aa_audit(type, profile, &sa, file_audit_cb);
}

+2 −2
Original line number Diff line number Diff line
@@ -107,14 +107,14 @@ struct apparmor_audit_data {
	void *profile;
	const char *name;
	const char *info;
	u32 request;
	u32 denied;
	union {
		/* these entries require a custom callback fn */
		struct {
			struct aa_profile *peer;
			struct {
				const char *target;
				u32 request;
				u32 denied;
				kuid_t ouid;
			} fs;
		};
+34 −0
Original line number Diff line number Diff line
@@ -66,6 +66,40 @@
extern const char aa_file_perm_chrs[];
extern const char *aa_file_perm_names[];

struct aa_perms {
	u32 allow;
	u32 audit;	/* set only when allow is set */

	u32 deny;	/* explicit deny, or conflict if allow also set */
	u32 quiet;	/* set only when ~allow | deny */
	u32 kill;	/* set only when ~allow | deny */
	u32 stop;	/* set only when ~allow | deny */

	u32 complain;	/* accumulates only used when ~allow & ~deny */
	u32 cond;	/* set only when ~allow and ~deny */

	u32 hide;	/* set only when  ~allow | deny */
	u32 prompt;	/* accumulates only used when ~allow & ~deny */

	/* Reserved:
	 * u32 subtree;	/ * set only when allow is set * /
	 */
	u16 xindex;
};

#define ALL_PERMS_MASK 0xffffffff

extern struct aa_perms allperms;

struct aa_profile;

void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
			u32 chrsmask, const char **names, u32 namesmask);
void aa_apply_modes_to_perms(struct aa_profile *profile,
			     struct aa_perms *perms);
void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
		      struct aa_perms *perms);

#endif /* __AA_PERM_H */
+102 −0
Original line number Diff line number Diff line
@@ -24,6 +24,10 @@
#include "include/perms.h"
#include "include/policy.h"

struct aa_perms allperms = { .allow = ALL_PERMS_MASK,
			     .quiet = ALL_PERMS_MASK,
			     .hide = ALL_PERMS_MASK };

/**
 * aa_split_fqname - split a fqname into a profile and namespace name
 * @fqname: a full qualified name in namespace profile format (NOT NULL)
@@ -188,6 +192,104 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
	*str = '\0';
}

void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
{
	const char *fmt = "%s";
	unsigned int i, perm = 1;
	bool prev = false;

	for (i = 0; i < 32; perm <<= 1, i++) {
		if (mask & perm) {
			audit_log_format(ab, fmt, names[i]);
			if (!prev) {
				prev = true;
				fmt = " %s";
			}
		}
	}
}

void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
			u32 chrsmask, const char **names, u32 namesmask)
{
	char str[33];

	audit_log_format(ab, "\"");
	if ((mask & chrsmask) && chrs) {
		aa_perm_mask_to_str(str, chrs, mask & chrsmask);
		mask &= ~chrsmask;
		audit_log_format(ab, "%s", str);
		if (mask & namesmask)
			audit_log_format(ab, " ");
	}
	if ((mask & namesmask) && names)
		aa_audit_perm_names(ab, names, mask & namesmask);
	audit_log_format(ab, "\"");
}

/**
 * aa_apply_modes_to_perms - apply namespace and profile flags to perms
 * @profile: that perms where computed from
 * @perms: perms to apply mode modifiers to
 *
 * TODO: split into profile and ns based flags for when accumulating perms
 */
void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms)
{
	switch (AUDIT_MODE(profile)) {
	case AUDIT_ALL:
		perms->audit = ALL_PERMS_MASK;
		/* fall through */
	case AUDIT_NOQUIET:
		perms->quiet = 0;
		break;
	case AUDIT_QUIET:
		perms->audit = 0;
		/* fall through */
	case AUDIT_QUIET_DENIED:
		perms->quiet = ALL_PERMS_MASK;
		break;
	}

	if (KILL_MODE(profile))
		perms->kill = ALL_PERMS_MASK;
	else if (COMPLAIN_MODE(profile))
		perms->complain = ALL_PERMS_MASK;
/*
 *  TODO:
 *	else if (PROMPT_MODE(profile))
 *		perms->prompt = ALL_PERMS_MASK;
 */
}

static u32 map_other(u32 x)
{
	return ((x & 0x3) << 8) |	/* SETATTR/GETATTR */
		((x & 0x1c) << 18) |	/* ACCEPT/BIND/LISTEN */
		((x & 0x60) << 19);	/* SETOPT/GETOPT */
}

void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
		      struct aa_perms *perms)
{
	perms->deny = 0;
	perms->kill = perms->stop = 0;
	perms->complain = perms->cond = 0;
	perms->hide = 0;
	perms->prompt = 0;
	perms->allow = dfa_user_allow(dfa, state);
	perms->audit = dfa_user_audit(dfa, state);
	perms->quiet = dfa_user_quiet(dfa, state);

	/* for v5 perm mapping in the policydb, the other set is used
	 * to extend the general perm set
	 */
	perms->allow |= map_other(dfa_other_allow(dfa, state));
	perms->audit |= map_other(dfa_other_audit(dfa, state));
	perms->quiet |= map_other(dfa_other_quiet(dfa, state));
//	perms->xindex = dfa_user_xindex(dfa, state);
}

/**
 * aa_policy_init - initialize a policy structure
 * @policy: policy to initialize  (NOT NULL)