Permalink
Browse files

LSM: shrink sizeof LSM specific portion of common_audit_data

Linus found that the gigantic size of the common audit data caused a big
perf hit on something as simple as running stat() in a loop.  This patch
requires LSMs to declare the LSM specific portion separately rather than
doing it in a union.  Thus each LSM can be responsible for shrinking their
portion and don't have to pay a penalty just because other LSMs have a
bigger space requirement.

Signed-off-by: Eric Paris <eparis@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information...
1 parent 9569412 commit 3b3b0e4fc15efa507b902d90cea39e496a523c3b @eparis eparis committed with Apr 3, 2012
View
@@ -72,61 +72,15 @@ struct common_audit_data {
/* this union contains LSM specific data */
union {
#ifdef CONFIG_SECURITY_SMACK
- /* SMACK data */
- struct smack_audit_data {
- const char *function;
- char *subject;
- char *object;
- char *request;
- int result;
- } smack_audit_data;
+ struct smack_audit_data *smack_audit_data;
#endif
#ifdef CONFIG_SECURITY_SELINUX
- /* SELinux data */
- struct {
- u32 ssid;
- u32 tsid;
- u16 tclass;
- u32 requested;
- u32 audited;
- u32 denied;
- /*
- * auditdeny is a bit tricky and unintuitive. See the
- * comments in avc.c for it's meaning and usage.
- */
- u32 auditdeny;
- struct av_decision *avd;
- int result;
- } selinux_audit_data;
+ struct selinux_audit_data *selinux_audit_data;
#endif
#ifdef CONFIG_SECURITY_APPARMOR
- struct {
- int error;
- int op;
- int type;
- void *profile;
- const char *name;
- const char *info;
- union {
- void *target;
- struct {
- long pos;
- void *target;
- } iface;
- struct {
- int rlim;
- unsigned long max;
- } rlim;
- struct {
- const char *target;
- u32 request;
- u32 denied;
- uid_t ouid;
- } fs;
- };
- } apparmor_audit_data;
+ struct apparmor_audit_data *apparmor_audit_data;
#endif
- };
+ }; /* per LSM data pointer union */
/* these callback will be implemented by a specific LSM */
void (*lsm_pre_audit)(struct audit_buffer *, void *);
void (*lsm_post_audit)(struct audit_buffer *, void *);
View
@@ -115,23 +115,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[sa->aad->type]);
}
- if (sa->aad.op) {
+ if (sa->aad->op) {
audit_log_format(ab, " operation=");
- audit_log_string(ab, op_table[sa->aad.op]);
+ audit_log_string(ab, op_table[sa->aad->op]);
}
- if (sa->aad.info) {
+ if (sa->aad->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, sa->aad->info);
+ if (sa->aad->error)
+ audit_log_format(ab, " error=%d", sa->aad->error);
}
- if (sa->aad.profile) {
- struct aa_profile *profile = sa->aad.profile;
+ if (sa->aad->profile) {
+ struct aa_profile *profile = sa->aad->profile;
pid_t pid;
rcu_read_lock();
pid = rcu_dereference(tsk->real_parent)->pid;
@@ -145,9 +145,9 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
audit_log_untrustedstring(ab, profile->base.hname);
}
- if (sa->aad.name) {
+ if (sa->aad->name) {
audit_log_format(ab, " name=");
- audit_log_untrustedstring(ab, sa->aad.name);
+ audit_log_untrustedstring(ab, sa->aad->name);
}
}
@@ -159,7 +159,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;
+ sa->aad->type = type;
sa->lsm_pre_audit = audit_pre;
sa->lsm_post_audit = cb;
common_lsm_audit(sa);
@@ -184,7 +184,7 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
BUG_ON(!profile);
if (type == AUDIT_APPARMOR_AUTO) {
- if (likely(!sa->aad.error)) {
+ if (likely(!sa->aad->error)) {
if (AUDIT_MODE(profile) != AUDIT_ALL)
return 0;
type = AUDIT_APPARMOR_AUDIT;
@@ -196,21 +196,21 @@ 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 sa->aad->error;
if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
type = AUDIT_APPARMOR_KILL;
if (!unconfined(profile))
- sa->aad.profile = profile;
+ sa->aad->profile = profile;
aa_audit_msg(type, sa, cb);
- if (sa->aad.type == AUDIT_APPARMOR_KILL)
+ if (sa->aad->type == AUDIT_APPARMOR_KILL)
(void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
- if (sa->aad.type == AUDIT_APPARMOR_ALLOWED)
- return complain_error(sa->aad.error);
+ if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
+ return complain_error(sa->aad->error);
- return sa->aad.error;
+ return sa->aad->error;
}
@@ -64,11 +64,13 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task,
struct audit_cache *ent;
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, CAP);
+ sa.aad = &aad;
sa.tsk = task;
sa.u.cap = cap;
- sa.aad.op = OP_CAPABLE;
- sa.aad.error = error;
+ sa.aad->op = OP_CAPABLE;
+ sa.aad->error = error;
if (likely(!error)) {
/* test if auditing is being forced */
View
@@ -67,22 +67,22 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
struct common_audit_data *sa = va;
uid_t fsuid = current_fsuid();
- if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
+ if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " requested_mask=");
- audit_file_mask(ab, sa->aad.fs.request);
+ audit_file_mask(ab, sa->aad->fs.request);
}
- if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) {
+ if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " denied_mask=");
- audit_file_mask(ab, sa->aad.fs.denied);
+ audit_file_mask(ab, sa->aad->fs.denied);
}
- if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
+ if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " fsuid=%d", fsuid);
- audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid);
+ audit_log_format(ab, " ouid=%d", sa->aad->fs.ouid);
}
- if (sa->aad.fs.target) {
+ if (sa->aad->fs.target) {
audit_log_format(ab, " target=");
- audit_log_untrustedstring(ab, sa->aad.fs.target);
+ audit_log_untrustedstring(ab, sa->aad->fs.target);
}
}
@@ -107,45 +107,47 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
{
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = op,
- sa.aad.fs.request = request;
- sa.aad.name = name;
- sa.aad.fs.target = target;
- sa.aad.fs.ouid = ouid;
- sa.aad.info = info;
- sa.aad.error = error;
-
- if (likely(!sa.aad.error)) {
+ 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)) {
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;
+ sa.aad->fs.request &= mask;
- if (likely(!sa.aad.fs.request))
+ if (likely(!sa.aad->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;
+ sa.aad->fs.request = sa.aad->fs.request & ~perms->allow;
- if (sa.aad.fs.request & perms->kill)
+ if (sa.aad->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 ((sa.aad->fs.request & perms->quiet) &&
AUDIT_MODE(profile) != AUDIT_NOQUIET &&
AUDIT_MODE(profile) != AUDIT_ALL)
- sa.aad.fs.request &= ~perms->quiet;
+ sa.aad->fs.request &= ~perms->quiet;
- if (!sa.aad.fs.request)
- return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
+ if (!sa.aad->fs.request)
+ return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
}
- sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow;
+ sa.aad->fs.denied = sa.aad->fs.request & ~perms->allow;
return aa_audit(type, profile, gfp, &sa, file_audit_cb);
}
@@ -103,7 +103,33 @@ enum aa_ops {
};
-/* define a short hand for apparmor_audit_data portion of common_audit_data */
+struct apparmor_audit_data {
+ int error;
+ int op;
+ int type;
+ void *profile;
+ const char *name;
+ const char *info;
+ union {
+ void *target;
+ struct {
+ long pos;
+ void *target;
+ } iface;
+ struct {
+ int rlim;
+ unsigned long max;
+ } rlim;
+ struct {
+ const char *target;
+ u32 request;
+ u32 denied;
+ uid_t ouid;
+ } fs;
+ };
+};
+
+/* define a short hand for apparmor_audit_data structure */
#define aad apparmor_audit_data
void aa_audit_msg(int type, struct common_audit_data *sa,
View
@@ -26,7 +26,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
audit_log_format(ab, " target=");
- audit_log_untrustedstring(ab, sa->aad.target);
+ audit_log_untrustedstring(ab, sa->aad->target);
}
/**
@@ -41,10 +41,12 @@ static int aa_audit_ptrace(struct aa_profile *profile,
struct aa_profile *target, int error)
{
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = OP_PTRACE;
- sa.aad.target = target;
- sa.aad.error = error;
+ sa.aad = &aad;
+ aad.op = OP_PTRACE;
+ aad.target = target;
+ aad.error = error;
return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
audit_cb);
View
@@ -65,8 +65,10 @@ void aa_info_message(const char *str)
{
if (audit_enabled) {
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.info = str;
+ sa.aad = &aad;
+ aad.info = str;
aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
}
printk(KERN_INFO "AppArmor: %s\n", str);
View
@@ -588,10 +588,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
error = aa_setprocattr_permipc(args);
} else {
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = OP_SETPROCATTR;
- sa.aad.info = name;
- sa.aad.error = -EINVAL;
+ sa.aad = &aad;
+ aad.op = OP_SETPROCATTR;
+ aad.info = name;
+ aad.error = -EINVAL;
return aa_audit(AUDIT_APPARMOR_DENIED,
__aa_current_profile(), GFP_KERNEL,
&sa, NULL);
View
@@ -964,11 +964,13 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
int error)
{
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = op;
- sa.aad.name = name;
- sa.aad.info = info;
- sa.aad.error = error;
+ sa.aad = &aad;
+ aad.op = op;
+ aad.name = name;
+ aad.info = info;
+ aad.error = error;
return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
&sa, NULL);
Oops, something went wrong.

0 comments on commit 3b3b0e4

Please sign in to comment.