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

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

apparmor: change aad apparmor_audit_data macro to a fn macro



The aad macro can replace aad strings when it is not intended to. Switch
to a fn macro so it is only applied when intended.

Also at the same time cleanup audit_data initialization by putting
common boiler plate behind a macro, and dropping the gfp_t parameter
which will become useless.

Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent 47f6e5cc
Loading
Loading
Loading
Loading
+20 −22
Original line number Diff line number Diff line
@@ -62,23 +62,23 @@ static void audit_pre(struct audit_buffer *ab, void *ca)

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

	if (sa->aad->op) {
	if (aad(sa)->op) {
		audit_log_format(ab, " operation=");
		audit_log_string(ab, sa->aad->op);
		audit_log_string(ab, aad(sa)->op);
	}

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

	if (sa->aad->profile) {
		struct aa_profile *profile = sa->aad->profile;
	if (aad(sa)->profile) {
		struct aa_profile *profile = aad(sa)->profile;
		if (profile->ns != root_ns) {
			audit_log_format(ab, " namespace=");
			audit_log_untrustedstring(ab, profile->ns->base.hname);
@@ -87,9 +87,9 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
		audit_log_untrustedstring(ab, profile->base.hname);
	}

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

@@ -101,7 +101,7 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
void aa_audit_msg(int type, struct common_audit_data *sa,
		  void (*cb) (struct audit_buffer *, void *))
{
	sa->aad->type = type;
	aad(sa)->type = type;
	common_lsm_audit(sa, audit_pre, cb);
}

@@ -109,7 +109,6 @@ void aa_audit_msg(int type, struct common_audit_data *sa,
 * 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)
 * @gfp: allocation flags to use
 * @sa: audit event (NOT NULL)
 * @cb: optional callback fn for type specific fields (MAYBE NULL)
 *
@@ -117,14 +116,13 @@ void aa_audit_msg(int type, struct common_audit_data *sa,
 *
 * Returns: error on failure
 */
int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
	     struct common_audit_data *sa,
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
	     void (*cb) (struct audit_buffer *, void *))
{
	BUG_ON(!profile);

	if (type == AUDIT_APPARMOR_AUTO) {
		if (likely(!sa->aad->error)) {
		if (likely(!aad(sa)->error)) {
			if (AUDIT_MODE(profile) != AUDIT_ALL)
				return 0;
			type = AUDIT_APPARMOR_AUDIT;
@@ -136,23 +134,23 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
	if (AUDIT_MODE(profile) == AUDIT_QUIET ||
	    (type == AUDIT_APPARMOR_DENIED &&
	     AUDIT_MODE(profile) == AUDIT_QUIET))
		return sa->aad->error;
		return aad(sa)->error;

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

	if (!unconfined(profile))
		sa->aad->profile = profile;
		aad(sa)->profile = profile;

	aa_audit_msg(type, sa, cb);

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

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

	return sa->aad->error;
	return aad(sa)->error;
}
+3 −7
Original line number Diff line number Diff line
@@ -66,13 +66,9 @@ static int audit_caps(struct aa_profile *profile, int cap, int error)
{
	struct audit_cache *ent;
	int type = AUDIT_APPARMOR_AUTO;
	struct common_audit_data sa;
	struct apparmor_audit_data aad = {0,};
	sa.type = LSM_AUDIT_DATA_CAP;
	sa.aad = &aad;
	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE);
	sa.u.cap = cap;
	sa.aad->op = OP_CAPABLE;
	sa.aad->error = error;
	aad(&sa)->error = error;

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

	return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);
	return aa_audit(type, profile, &sa, audit_cb);
}

/**
+6 −7
Original line number Diff line number Diff line
@@ -508,8 +508,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
	aa_clear_task_ctx_trans(ctx);

audit:
	error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
			      name,
	error = aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name,
			      new_profile ? new_profile->base.hname : NULL,
			      cond.uid, info, error);

@@ -714,9 +713,9 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)

audit:
	if (!permtest)
		error = aa_audit_file(profile, &perms, GFP_KERNEL,
				      OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
				      target, GLOBAL_ROOT_UID, info, error);
		error = aa_audit_file(profile, &perms, OP_CHANGE_HAT,
				      AA_MAY_CHANGEHAT, NULL, target,
				      GLOBAL_ROOT_UID, info, error);

out:
	aa_put_profile(hat);
@@ -842,8 +841,8 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,

audit:
	if (!permtest)
		error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
				      name, hname, GLOBAL_ROOT_UID, info, error);
		error = aa_audit_file(profile, &perms, op, request, name,
				      hname, GLOBAL_ROOT_UID, info, error);

	aa_put_ns(ns);
	aa_put_profile(target);
+34 −35
Original line number Diff line number Diff line
@@ -67,24 +67,24 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
	struct common_audit_data *sa = va;
	kuid_t fsuid = current_fsuid();

	if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
	if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
		audit_log_format(ab, " requested_mask=");
		audit_file_mask(ab, sa->aad->fs.request);
		audit_file_mask(ab, aad(sa)->fs.request);
	}
	if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) {
	if (aad(sa)->fs.denied & AA_AUDIT_FILE_MASK) {
		audit_log_format(ab, " denied_mask=");
		audit_file_mask(ab, sa->aad->fs.denied);
		audit_file_mask(ab, aad(sa)->fs.denied);
	}
	if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
	if (aad(sa)->fs.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, sa->aad->fs.ouid));
				 from_kuid(&init_user_ns, aad(sa)->fs.ouid));
	}

	if (sa->aad->fs.target) {
	if (aad(sa)->fs.target) {
		audit_log_format(ab, " target=");
		audit_log_untrustedstring(ab, sa->aad->fs.target);
		audit_log_untrustedstring(ab, aad(sa)->fs.target);
	}
}

@@ -104,54 +104,53 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
 * Returns: %0 or error on failure
 */
int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
		  gfp_t gfp, const char *op, u32 request, const char *name,
		  const char *op, u32 request, const char *name,
		  const char *target, kuid_t ouid, const char *info, int error)
{
	int type = AUDIT_APPARMOR_AUTO;
	struct common_audit_data sa;
	struct apparmor_audit_data aad = {0,};
	sa.type = LSM_AUDIT_DATA_TASK;
	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op);

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

	if (likely(!sa.aad->error)) {

	if (likely(!aad(&sa)->error)) {
		u32 mask = perms->audit;

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

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

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

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

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

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

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

/**
@@ -302,8 +301,8 @@ int aa_path_perm(const char *op, struct aa_profile *profile,
		if (request & ~perms.allow)
			error = -EACCES;
	}
	error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, name,
			      NULL, cond->uid, info, error);
	error = aa_audit_file(profile, &perms, op, request, name, NULL,
			      cond->uid, info, error);
	kfree(buffer);

	return error;
@@ -430,7 +429,7 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
	error = 0;

audit:
	error = aa_audit_file(profile, &lperms, GFP_KERNEL, OP_LINK, request,
	error = aa_audit_file(profile, &lperms, OP_LINK, request,
			      lname, tname, cond.uid, info, error);
	kfree(buffer);
	kfree(buffer2);
+31 −12
Original line number Diff line number Diff line
@@ -108,34 +108,53 @@ struct apparmor_audit_data {
	const char *name;
	const char *info;
	union {
		void *target;
		/* these entries require a custom callback fn */
		struct {
			struct aa_profile *peer;
			struct {
				const char *target;
				u32 request;
				u32 denied;
				kuid_t ouid;
			} fs;
		};
		struct {
			const char *name;
			long pos;
			const char *ns;
			void *target;
		} iface;
		struct {
			int rlim;
			unsigned long max;
		} rlim;
		struct {
			const char *target;
			u32 request;
			u32 denied;
			kuid_t ouid;
		} fs;
	};
};

/* define a short hand for apparmor_audit_data structure */
#define aad apparmor_audit_data
/* macros for dealing with  apparmor_audit_data structure */
#define aad(SA) ((SA)->apparmor_audit_data)
#define DEFINE_AUDIT_DATA(NAME, T, X)					\
	/* TODO: cleanup audit init so we don't need _aad = {0,} */	\
	struct apparmor_audit_data NAME ## _aad = { .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,
		  void (*cb) (struct audit_buffer *, void *));
int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
	     struct common_audit_data *sa,
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
	     void (*cb) (struct audit_buffer *, void *));

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


static inline int complain_error(int error)
{
	if (error == -EPERM || error == -EACCES)
Loading