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

apparmor: combine common_audit_data and apparmor_audit_data



Everywhere where common_audit_data is used apparmor audit_data is also
used. We can simplify the code and drop the use of the aad macro
everywhere by combining the two structures.

Reviewed-by: default avatarGeorgia Garcia <georgia.garcia@canonical.com>
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent 79ddd4a7
Loading
Loading
Loading
Loading
+35 −35
Original line number Diff line number Diff line
@@ -85,37 +85,36 @@ static const char *const aa_class_names[] = {
/**
 * audit_pre() - core AppArmor function.
 * @ab: audit buffer to fill (NOT NULL)
 * @ca: audit structure containing data to audit (NOT NULL)
 * @va: audit structure containing data to audit (NOT NULL)
 *
 * Record common AppArmor audit data from @sa
 * Record common AppArmor audit data from @va
 */
static void audit_pre(struct audit_buffer *ab, void *ca)
static void audit_pre(struct audit_buffer *ab, void *va)
{
	struct common_audit_data *sa = ca;
	struct apparmor_audit_data *ad = aad_of_va(va);

	if (aa_g_audit_header) {
		audit_log_format(ab, "apparmor=\"%s\"",
				 aa_audit_type[aad(sa)->type]);
				 aa_audit_type[ad->type]);
	}

	if (aad(sa)->op) {
		audit_log_format(ab, " operation=\"%s\"", aad(sa)->op);
	}
	if (ad->op)
		audit_log_format(ab, " operation=\"%s\"", ad->op);

	if (aad(sa)->class)
	if (ad->class)
		audit_log_format(ab, " class=\"%s\"",
				 aad(sa)->class <= AA_CLASS_LAST ?
				 aa_class_names[aad(sa)->class] :
				 ad->class <= AA_CLASS_LAST ?
				 aa_class_names[ad->class] :
				 "unknown");

	if (aad(sa)->info) {
		audit_log_format(ab, " info=\"%s\"", aad(sa)->info);
		if (aad(sa)->error)
			audit_log_format(ab, " error=%d", aad(sa)->error);
	if (ad->info) {
		audit_log_format(ab, " info=\"%s\"", ad->info);
		if (ad->error)
			audit_log_format(ab, " error=%d", ad->error);
	}

	if (aad(sa)->label) {
		struct aa_label *label = aad(sa)->label;
	if (ad->label) {
		struct aa_label *label = ad->label;

		if (label_isprofile(label)) {
			struct aa_profile *profile = labels_profile(label);
@@ -134,43 +133,44 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
		}
	}

	if (aad(sa)->name) {
	if (ad->name) {
		audit_log_format(ab, " name=");
		audit_log_untrustedstring(ab, aad(sa)->name);
		audit_log_untrustedstring(ab, ad->name);
	}
}

/**
 * aa_audit_msg - Log a message to the audit subsystem
 * @type: audit type for the message
 * @sa: audit event structure (NOT NULL)
 * @ad: audit event structure (NOT NULL)
 * @cb: optional callback fn for type specific fields (MAYBE NULL)
 */
void aa_audit_msg(int type, struct common_audit_data *sa,
void aa_audit_msg(int type, struct apparmor_audit_data *ad,
		  void (*cb) (struct audit_buffer *, void *))
{
	aad(sa)->type = type;
	common_lsm_audit(sa, audit_pre, cb);
	ad->type = type;
	common_lsm_audit(&ad->common, audit_pre, cb);
}

/**
 * aa_audit - Log a profile based audit event to the audit subsystem
 * @type: audit type for the message
 * @profile: profile to check against (NOT NULL)
 * @sa: audit event (NOT NULL)
 * @ad: audit event (NOT NULL)
 * @cb: optional callback fn for type specific fields (MAYBE NULL)
 *
 * Handle default message switching based off of audit mode flags
 *
 * Returns: error on failure
 */
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
int aa_audit(int type, struct aa_profile *profile,
	     struct apparmor_audit_data *ad,
	     void (*cb) (struct audit_buffer *, void *))
{
	AA_BUG(!profile);

	if (type == AUDIT_APPARMOR_AUTO) {
		if (likely(!aad(sa)->error)) {
		if (likely(!ad->error)) {
			if (AUDIT_MODE(profile) != AUDIT_ALL)
				return 0;
			type = AUDIT_APPARMOR_AUDIT;
@@ -182,24 +182,24 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
	if (AUDIT_MODE(profile) == AUDIT_QUIET ||
	    (type == AUDIT_APPARMOR_DENIED &&
	     AUDIT_MODE(profile) == AUDIT_QUIET_DENIED))
		return aad(sa)->error;
		return ad->error;

	if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
		type = AUDIT_APPARMOR_KILL;

	aad(sa)->label = &profile->label;
	ad->label = &profile->label;

	aa_audit_msg(type, sa, cb);
	aa_audit_msg(type, ad, cb);

	if (aad(sa)->type == AUDIT_APPARMOR_KILL)
	if (ad->type == AUDIT_APPARMOR_KILL)
		(void)send_sig_info(SIGKILL, NULL,
			sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
				    sa->u.tsk : current);
			ad->common.type == LSM_AUDIT_DATA_TASK &&
			ad->common.u.tsk ? ad->common.u.tsk : current);

	if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED)
		return complain_error(aad(sa)->error);
	if (ad->type == AUDIT_APPARMOR_ALLOWED)
		return complain_error(ad->error);

	return aad(sa)->error;
	return ad->error;
}

struct aa_audit_rule {
+12 −12
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)

/**
 * audit_caps - audit a capability
 * @sa: audit data
 * @as: audit data
 * @profile: profile being tested for confinement (NOT NULL)
 * @cap: capability tested
 * @error: error code returned by test
@@ -59,9 +59,9 @@ static void audit_cb(struct audit_buffer *ab, void *va)
 * Do auditing of capability and handle, audit/complain/kill modes switching
 * and duplicate message elimination.
 *
 * Returns: 0 or sa->error on success,  error code on failure
 * Returns: 0 or ad->error on success,  error code on failure
 */
static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile,
		      int cap, int error)
{
	struct aa_ruleset *rules = list_first_entry(&profile->rules,
@@ -69,7 +69,7 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
	struct audit_cache *ent;
	int type = AUDIT_APPARMOR_AUTO;

	aad(sa)->error = error;
	ad->error = error;

	if (likely(!error)) {
		/* test if auditing is being forced */
@@ -101,7 +101,7 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
	}
	put_cpu_var(audit_cache);

	return aa_audit(type, profile, sa, audit_cb);
	return aa_audit(type, profile, ad, audit_cb);
}

/**
@@ -109,12 +109,12 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
 * @profile: profile being enforced    (NOT NULL, NOT unconfined)
 * @cap: capability to test if allowed
 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
 * @sa: audit data (MAY BE NULL indicating no auditing)
 * @ad: audit data (MAY BE NULL indicating no auditing)
 *
 * Returns: 0 if allowed else -EPERM
 */
static int profile_capable(struct aa_profile *profile, int cap,
			   unsigned int opts, struct common_audit_data *sa)
			   unsigned int opts, struct apparmor_audit_data *ad)
{
	struct aa_ruleset *rules = list_first_entry(&profile->rules,
						    typeof(*rules), list);
@@ -132,10 +132,10 @@ static int profile_capable(struct aa_profile *profile, int cap,
		/* audit the cap request in complain mode but note that it
		 * should be optional.
		 */
		aad(sa)->info = "optional: no audit";
		ad->info = "optional: no audit";
	}

	return audit_caps(sa, profile, cap, error);
	return audit_caps(ad, profile, cap, error);
}

/**
@@ -152,11 +152,11 @@ int aa_capable(struct aa_label *label, int cap, unsigned int opts)
{
	struct aa_profile *profile;
	int error = 0;
	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE);
	DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE);

	sa.u.cap = cap;
	ad.common.u.cap = cap;
	error = fn_for_each_confined(label, profile,
			profile_capable(profile, cap, opts, &sa));
			profile_capable(profile, cap, opts, &ad));

	return error;
}
+34 −34
Original line number Diff line number Diff line
@@ -44,33 +44,34 @@ static u32 map_mask_to_chr_mask(u32 mask)
static void file_audit_cb(struct audit_buffer *ab, void *va)
{
	struct common_audit_data *sa = va;
	struct apparmor_audit_data *ad = aad(sa);
	kuid_t fsuid = current_fsuid();
	char str[10];

	if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
	if (ad->request & AA_AUDIT_FILE_MASK) {
		aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs,
				    map_mask_to_chr_mask(aad(sa)->request));
				    map_mask_to_chr_mask(ad->request));
		audit_log_format(ab, " requested_mask=\"%s\"", str);
	}
	if (aad(sa)->denied & AA_AUDIT_FILE_MASK) {
	if (ad->denied & AA_AUDIT_FILE_MASK) {
		aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs,
				    map_mask_to_chr_mask(aad(sa)->denied));
				    map_mask_to_chr_mask(ad->denied));
		audit_log_format(ab, " denied_mask=\"%s\"", str);
	}
	if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
	if (ad->request & AA_AUDIT_FILE_MASK) {
		audit_log_format(ab, " fsuid=%d",
				 from_kuid(&init_user_ns, fsuid));
		audit_log_format(ab, " ouid=%d",
				 from_kuid(&init_user_ns, aad(sa)->fs.ouid));
				 from_kuid(&init_user_ns, ad->fs.ouid));
	}

	if (aad(sa)->peer) {
	if (ad->peer) {
		audit_log_format(ab, " target=");
		aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
		aa_label_xaudit(ab, labels_ns(ad->label), ad->peer,
				FLAG_VIEW_SUBNS, GFP_KERNEL);
	} else if (aad(sa)->fs.target) {
	} else if (ad->fs.target) {
		audit_log_format(ab, " target=");
		audit_log_untrustedstring(ab, aad(sa)->fs.target);
		audit_log_untrustedstring(ab, ad->fs.target);
	}
}

@@ -95,50 +96,49 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms,
		  kuid_t ouid, const char *info, int error)
{
	int type = AUDIT_APPARMOR_AUTO;
	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op);

	sa.u.tsk = NULL;
	aad(&sa)->request = request;
	aad(&sa)->name = name;
	aad(&sa)->fs.target = target;
	aad(&sa)->peer = tlabel;
	aad(&sa)->fs.ouid = ouid;
	aad(&sa)->info = info;
	aad(&sa)->error = error;
	sa.u.tsk = NULL;

	if (likely(!aad(&sa)->error)) {
	DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op);

	ad.request = request;
	ad.name = name;
	ad.fs.target = target;
	ad.peer = tlabel;
	ad.fs.ouid = ouid;
	ad.info = info;
	ad.error = error;
	ad.common.u.tsk = NULL;

	if (likely(!ad.error)) {
		u32 mask = perms->audit;

		if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
			mask = 0xffff;

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

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

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

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

		if (!aad(&sa)->request)
			return aad(&sa)->error;
		if (!ad.request)
			return ad.error;
	}

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

static int path_name(const char *op, struct aa_label *label,
+18 −16
Original line number Diff line number Diff line
@@ -152,33 +152,35 @@ struct apparmor_audit_data {
			unsigned long flags;
		} mnt;
	};

	struct common_audit_data common;
};

/* macros for dealing with  apparmor_audit_data structure */
#define aad(SA) ((SA)->apparmor_audit_data)
#define aad(SA) (container_of(SA, struct apparmor_audit_data, common))
#define aad_of_va(VA) aad((struct common_audit_data *)(VA))

#define DEFINE_AUDIT_DATA(NAME, T, C, X)				\
	/* TODO: cleanup audit init so we don't need _aad = {0,} */	\
	struct apparmor_audit_data NAME ## _aad = {                     \
	struct apparmor_audit_data NAME = {				\
		.class = (C),						\
		.op = (X),                                              \
	};                                                              \
	struct common_audit_data NAME =					\
	{								\
	.type = (T),							\
	.u.tsk = NULL,							\
	};								\
	NAME.apparmor_audit_data = &(NAME ## _aad)

void aa_audit_msg(int type, struct common_audit_data *sa,
		.common.type = (T),					\
		.common.u.tsk = NULL,					\
		.common.apparmor_audit_data = &NAME,			\
	};

void aa_audit_msg(int type, struct apparmor_audit_data *ad,
		  void (*cb) (struct audit_buffer *, void *));
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
int aa_audit(int type, struct aa_profile *profile,
	     struct apparmor_audit_data *ad,
	     void (*cb) (struct audit_buffer *, void *));

#define aa_audit_error(ERROR, SA, CB)				\
#define aa_audit_error(ERROR, AD, CB)				\
({								\
	aad((SA))->error = (ERROR);				\
	aa_audit_msg(AUDIT_APPARMOR_ERROR, (SA), (CB));		\
	aad((SA))->error;					\
	(AD)->error = (ERROR);					\
	aa_audit_msg(AUDIT_APPARMOR_ERROR, (AD), (CB));		\
	(AD)->error;					\
})


+7 −6
Original line number Diff line number Diff line
@@ -65,9 +65,9 @@ static inline struct aa_sk_ctx *aa_sock(const struct sock *sk)
						     LSM_AUDIT_DATA_NONE, \
						     AA_CLASS_NET,        \
			  OP);						  \
	NAME.u.net = &(NAME ## _net);					  \
	aad(&NAME)->net.type = (T);					  \
	aad(&NAME)->net.protocol = (P)
	NAME.common.u.net = &(NAME ## _net);				  \
	NAME.net.type = (T);						  \
	NAME.net.protocol = (P)

#define DEFINE_AUDIT_SK(NAME, OP, SK)					\
	DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type,	\
@@ -94,16 +94,17 @@ struct aa_secmark {
extern struct aa_sfs_entry aa_sfs_entry_network[];

void audit_net_cb(struct audit_buffer *ab, void *va);
int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
int aa_profile_af_perm(struct aa_profile *profile,
		       struct apparmor_audit_data *ad,
		       u32 request, u16 family, int type);
int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
	       int type, int protocol);
static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
					struct common_audit_data *sa,
					struct apparmor_audit_data *ad,
					u32 request,
					struct sock *sk)
{
	return aa_profile_af_perm(profile, sa, request, sk->sk_family,
	return aa_profile_af_perm(profile, ad, request, sk->sk_family,
				  sk->sk_type);
}
int aa_sk_perm(const char *op, u32 request, struct sock *sk);
Loading