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>
This commit is contained in:
Родитель
95694129b4
Коммит
3b3b0e4fc1
|
@ -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 *);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
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(!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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -70,13 +70,13 @@ struct aa_ext {
|
|||
static void audit_cb(struct audit_buffer *ab, void *va)
|
||||
{
|
||||
struct common_audit_data *sa = va;
|
||||
if (sa->aad.iface.target) {
|
||||
struct aa_profile *name = sa->aad.iface.target;
|
||||
if (sa->aad->iface.target) {
|
||||
struct aa_profile *name = sa->aad->iface.target;
|
||||
audit_log_format(ab, " name=");
|
||||
audit_log_untrustedstring(ab, name->base.hname);
|
||||
}
|
||||
if (sa->aad.iface.pos)
|
||||
audit_log_format(ab, " offset=%ld", sa->aad.iface.pos);
|
||||
if (sa->aad->iface.pos)
|
||||
audit_log_format(ab, " offset=%ld", sa->aad->iface.pos);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,13 +94,15 @@ static int audit_iface(struct aa_profile *new, const char *name,
|
|||
{
|
||||
struct aa_profile *profile = __aa_current_profile();
|
||||
struct common_audit_data sa;
|
||||
struct apparmor_audit_data aad = {0,};
|
||||
COMMON_AUDIT_DATA_INIT(&sa, NONE);
|
||||
sa.aad = &aad;
|
||||
if (e)
|
||||
sa.aad.iface.pos = e->pos - e->start;
|
||||
sa.aad.iface.target = new;
|
||||
sa.aad.name = name;
|
||||
sa.aad.info = info;
|
||||
sa.aad.error = error;
|
||||
aad.iface.pos = e->pos - e->start;
|
||||
aad.iface.target = new;
|
||||
aad.name = name;
|
||||
aad.info = info;
|
||||
aad.error = error;
|
||||
|
||||
return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
|
||||
audit_cb);
|
||||
|
|
|
@ -34,7 +34,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
|
|||
struct common_audit_data *sa = va;
|
||||
|
||||
audit_log_format(ab, " rlimit=%s value=%lu",
|
||||
rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max);
|
||||
rlim_names[sa->aad->rlim.rlim], sa->aad->rlim.max);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,12 +50,14 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource,
|
|||
unsigned long value, int error)
|
||||
{
|
||||
struct common_audit_data sa;
|
||||
struct apparmor_audit_data aad = {0,};
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&sa, NONE);
|
||||
sa.aad.op = OP_SETRLIMIT,
|
||||
sa.aad.rlim.rlim = resource;
|
||||
sa.aad.rlim.max = value;
|
||||
sa.aad.error = error;
|
||||
sa.aad = &aad;
|
||||
aad.op = OP_SETRLIMIT,
|
||||
aad.rlim.rlim = resource;
|
||||
aad.rlim.max = value;
|
||||
aad.error = error;
|
||||
return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
|
||||
audit_cb);
|
||||
}
|
||||
|
|
|
@ -436,9 +436,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
|
|||
{
|
||||
struct common_audit_data *ad = a;
|
||||
audit_log_format(ab, "avc: %s ",
|
||||
ad->selinux_audit_data.denied ? "denied" : "granted");
|
||||
avc_dump_av(ab, ad->selinux_audit_data.tclass,
|
||||
ad->selinux_audit_data.audited);
|
||||
ad->selinux_audit_data->denied ? "denied" : "granted");
|
||||
avc_dump_av(ab, ad->selinux_audit_data->tclass,
|
||||
ad->selinux_audit_data->audited);
|
||||
audit_log_format(ab, " for ");
|
||||
}
|
||||
|
||||
|
@ -452,9 +452,9 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
|
|||
{
|
||||
struct common_audit_data *ad = a;
|
||||
audit_log_format(ab, " ");
|
||||
avc_dump_query(ab, ad->selinux_audit_data.ssid,
|
||||
ad->selinux_audit_data.tsid,
|
||||
ad->selinux_audit_data.tclass);
|
||||
avc_dump_query(ab, ad->selinux_audit_data->ssid,
|
||||
ad->selinux_audit_data->tsid,
|
||||
ad->selinux_audit_data->tclass);
|
||||
}
|
||||
|
||||
/* This is the slow part of avc audit with big stack footprint */
|
||||
|
@ -464,10 +464,12 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
|||
unsigned flags)
|
||||
{
|
||||
struct common_audit_data stack_data;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
|
||||
if (!a) {
|
||||
a = &stack_data;
|
||||
COMMON_AUDIT_DATA_INIT(a, NONE);
|
||||
a->selinux_audit_data = &sad;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -481,12 +483,12 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
|||
(flags & MAY_NOT_BLOCK))
|
||||
return -ECHILD;
|
||||
|
||||
a->selinux_audit_data.tclass = tclass;
|
||||
a->selinux_audit_data.requested = requested;
|
||||
a->selinux_audit_data.ssid = ssid;
|
||||
a->selinux_audit_data.tsid = tsid;
|
||||
a->selinux_audit_data.audited = audited;
|
||||
a->selinux_audit_data.denied = denied;
|
||||
a->selinux_audit_data->tclass = tclass;
|
||||
a->selinux_audit_data->requested = requested;
|
||||
a->selinux_audit_data->ssid = ssid;
|
||||
a->selinux_audit_data->tsid = tsid;
|
||||
a->selinux_audit_data->audited = audited;
|
||||
a->selinux_audit_data->denied = denied;
|
||||
a->lsm_pre_audit = avc_audit_pre_callback;
|
||||
a->lsm_post_audit = avc_audit_post_callback;
|
||||
common_lsm_audit(a);
|
||||
|
@ -523,7 +525,7 @@ inline int avc_audit(u32 ssid, u32 tsid,
|
|||
if (unlikely(denied)) {
|
||||
audited = denied & avd->auditdeny;
|
||||
/*
|
||||
* a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in
|
||||
* a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in
|
||||
* this field means that ANY denials should NOT be audited if
|
||||
* the policy contains an explicit dontaudit rule for that
|
||||
* permission. Take notice that this is unrelated to the
|
||||
|
@ -532,15 +534,15 @@ inline int avc_audit(u32 ssid, u32 tsid,
|
|||
*
|
||||
* denied == READ
|
||||
* avd.auditdeny & ACCESS == 0 (not set means explicit rule)
|
||||
* selinux_audit_data.auditdeny & ACCESS == 1
|
||||
* selinux_audit_data->auditdeny & ACCESS == 1
|
||||
*
|
||||
* We will NOT audit the denial even though the denied
|
||||
* permission was READ and the auditdeny checks were for
|
||||
* ACCESS
|
||||
*/
|
||||
if (a &&
|
||||
a->selinux_audit_data.auditdeny &&
|
||||
!(a->selinux_audit_data.auditdeny & avd->auditdeny))
|
||||
a->selinux_audit_data->auditdeny &&
|
||||
!(a->selinux_audit_data->auditdeny & avd->auditdeny))
|
||||
audited = 0;
|
||||
} else if (result)
|
||||
audited = denied = requested;
|
||||
|
|
|
@ -1420,6 +1420,7 @@ static int cred_has_capability(const struct cred *cred,
|
|||
int cap, int audit)
|
||||
{
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
struct av_decision avd;
|
||||
u16 sclass;
|
||||
u32 sid = cred_sid(cred);
|
||||
|
@ -1427,6 +1428,7 @@ static int cred_has_capability(const struct cred *cred,
|
|||
int rc;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, CAP);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.tsk = current;
|
||||
ad.u.cap = cap;
|
||||
|
||||
|
@ -1492,9 +1494,11 @@ static int inode_has_perm_noadp(const struct cred *cred,
|
|||
unsigned flags)
|
||||
{
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, INODE);
|
||||
ad.u.inode = inode;
|
||||
ad.selinux_audit_data = &sad;
|
||||
return inode_has_perm(cred, inode, perms, &ad, flags);
|
||||
}
|
||||
|
||||
|
@ -1507,9 +1511,11 @@ static inline int dentry_has_perm(const struct cred *cred,
|
|||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
|
||||
ad.u.dentry = dentry;
|
||||
ad.selinux_audit_data = &sad;
|
||||
return inode_has_perm(cred, inode, av, &ad, 0);
|
||||
}
|
||||
|
||||
|
@ -1522,9 +1528,11 @@ static inline int path_has_perm(const struct cred *cred,
|
|||
{
|
||||
struct inode *inode = path->dentry->d_inode;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, PATH);
|
||||
ad.u.path = *path;
|
||||
ad.selinux_audit_data = &sad;
|
||||
return inode_has_perm(cred, inode, av, &ad, 0);
|
||||
}
|
||||
|
||||
|
@ -1543,11 +1551,13 @@ static int file_has_perm(const struct cred *cred,
|
|||
struct file_security_struct *fsec = file->f_security;
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = cred_sid(cred);
|
||||
int rc;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, PATH);
|
||||
ad.u.path = file->f_path;
|
||||
ad.selinux_audit_data = &sad;
|
||||
|
||||
if (sid != fsec->sid) {
|
||||
rc = avc_has_perm(sid, fsec->sid,
|
||||
|
@ -1577,6 +1587,7 @@ static int may_create(struct inode *dir,
|
|||
struct superblock_security_struct *sbsec;
|
||||
u32 sid, newsid;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
int rc;
|
||||
|
||||
dsec = dir->i_security;
|
||||
|
@ -1587,6 +1598,7 @@ static int may_create(struct inode *dir,
|
|||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
|
||||
ad.u.dentry = dentry;
|
||||
ad.selinux_audit_data = &sad;
|
||||
|
||||
rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
|
||||
DIR__ADD_NAME | DIR__SEARCH,
|
||||
|
@ -1631,6 +1643,7 @@ static int may_link(struct inode *dir,
|
|||
{
|
||||
struct inode_security_struct *dsec, *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
u32 av;
|
||||
int rc;
|
||||
|
@ -1640,6 +1653,7 @@ static int may_link(struct inode *dir,
|
|||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
|
||||
ad.u.dentry = dentry;
|
||||
ad.selinux_audit_data = &sad;
|
||||
|
||||
av = DIR__SEARCH;
|
||||
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
|
||||
|
@ -1674,6 +1688,7 @@ static inline int may_rename(struct inode *old_dir,
|
|||
{
|
||||
struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
u32 av;
|
||||
int old_is_dir, new_is_dir;
|
||||
|
@ -1685,6 +1700,7 @@ static inline int may_rename(struct inode *old_dir,
|
|||
new_dsec = new_dir->i_security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
|
||||
ad.selinux_audit_data = &sad;
|
||||
|
||||
ad.u.dentry = old_dentry;
|
||||
rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
|
||||
|
@ -1970,6 +1986,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
|
|||
struct task_security_struct *new_tsec;
|
||||
struct inode_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
struct inode *inode = bprm->file->f_path.dentry->d_inode;
|
||||
int rc;
|
||||
|
||||
|
@ -2009,6 +2026,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
|
|||
}
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, PATH);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.path = bprm->file->f_path;
|
||||
|
||||
if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
|
||||
|
@ -2098,6 +2116,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
|
|||
struct files_struct *files)
|
||||
{
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
struct file *file, *devnull = NULL;
|
||||
struct tty_struct *tty;
|
||||
struct fdtable *fdt;
|
||||
|
@ -2135,6 +2154,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
|
|||
/* Revalidate access to inherited open files. */
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, INODE);
|
||||
ad.selinux_audit_data = &sad;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
for (;;) {
|
||||
|
@ -2472,6 +2492,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
|
|||
{
|
||||
const struct cred *cred = current_cred();
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
int rc;
|
||||
|
||||
rc = superblock_doinit(sb, data);
|
||||
|
@ -2483,6 +2504,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
|
|||
return 0;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.dentry = sb->s_root;
|
||||
return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
|
||||
}
|
||||
|
@ -2491,8 +2513,10 @@ static int selinux_sb_statfs(struct dentry *dentry)
|
|||
{
|
||||
const struct cred *cred = current_cred();
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.dentry = dentry->d_sb->s_root;
|
||||
return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
|
||||
}
|
||||
|
@ -2656,6 +2680,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
|
|||
{
|
||||
const struct cred *cred = current_cred();
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 perms;
|
||||
bool from_access;
|
||||
unsigned flags = mask & MAY_NOT_BLOCK;
|
||||
|
@ -2668,10 +2693,11 @@ static int selinux_inode_permission(struct inode *inode, int mask)
|
|||
return 0;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, INODE);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.inode = inode;
|
||||
|
||||
if (from_access)
|
||||
ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS;
|
||||
ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
|
||||
|
||||
perms = file_mask_to_av(inode->i_mode, mask);
|
||||
|
||||
|
@ -2737,6 +2763,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
|
|||
struct inode_security_struct *isec = inode->i_security;
|
||||
struct superblock_security_struct *sbsec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 newsid, sid = current_sid();
|
||||
int rc = 0;
|
||||
|
||||
|
@ -2751,6 +2778,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
|
|||
return -EPERM;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.dentry = dentry;
|
||||
|
||||
rc = avc_has_perm(sid, isec->sid, isec->sclass,
|
||||
|
@ -3345,10 +3373,12 @@ static int selinux_kernel_module_request(char *kmod_name)
|
|||
{
|
||||
u32 sid;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
|
||||
sid = task_sid(current);
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, KMOD);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.kmod_name = kmod_name;
|
||||
|
||||
return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
|
||||
|
@ -3721,12 +3751,14 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
|
|||
{
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 tsid = task_sid(task);
|
||||
|
||||
if (sksec->sid == SECINITSID_KERNEL)
|
||||
return 0;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.sk = sk;
|
||||
|
||||
return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
|
||||
|
@ -3805,6 +3837,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
|
|||
char *addrp;
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
struct sockaddr_in *addr4 = NULL;
|
||||
struct sockaddr_in6 *addr6 = NULL;
|
||||
unsigned short snum;
|
||||
|
@ -3831,6 +3864,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
|
|||
if (err)
|
||||
goto out;
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.sport = htons(snum);
|
||||
ad.u.net.family = family;
|
||||
err = avc_has_perm(sksec->sid, sid,
|
||||
|
@ -3864,6 +3898,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
|
|||
goto out;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.sport = htons(snum);
|
||||
ad.u.net.family = family;
|
||||
|
||||
|
@ -3897,6 +3932,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
|
|||
if (sksec->sclass == SECCLASS_TCP_SOCKET ||
|
||||
sksec->sclass == SECCLASS_DCCP_SOCKET) {
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
struct sockaddr_in *addr4 = NULL;
|
||||
struct sockaddr_in6 *addr6 = NULL;
|
||||
unsigned short snum;
|
||||
|
@ -3922,6 +3958,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
|
|||
TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.dport = htons(snum);
|
||||
ad.u.net.family = sk->sk_family;
|
||||
err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
|
||||
|
@ -4012,9 +4049,11 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
|
|||
struct sk_security_struct *sksec_other = other->sk_security;
|
||||
struct sk_security_struct *sksec_new = newsk->sk_security;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
int err;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.sk = other;
|
||||
|
||||
err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
|
||||
|
@ -4042,8 +4081,10 @@ static int selinux_socket_unix_may_send(struct socket *sock,
|
|||
struct sk_security_struct *ssec = sock->sk->sk_security;
|
||||
struct sk_security_struct *osec = other->sk->sk_security;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.sk = other->sk;
|
||||
|
||||
return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
|
||||
|
@ -4080,9 +4121,11 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
|
|||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
u32 sk_sid = sksec->sid;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
char *addrp;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.netif = skb->skb_iif;
|
||||
ad.u.net.family = family;
|
||||
err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
|
||||
|
@ -4111,6 +4154,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|||
u16 family = sk->sk_family;
|
||||
u32 sk_sid = sksec->sid;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
char *addrp;
|
||||
u8 secmark_active;
|
||||
u8 peerlbl_active;
|
||||
|
@ -4135,6 +4179,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|||
return 0;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.netif = skb->skb_iif;
|
||||
ad.u.net.family = family;
|
||||
err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
|
||||
|
@ -4471,6 +4516,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
|
|||
char *addrp;
|
||||
u32 peer_sid;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u8 secmark_active;
|
||||
u8 netlbl_active;
|
||||
u8 peerlbl_active;
|
||||
|
@ -4488,6 +4534,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
|
|||
return NF_DROP;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.netif = ifindex;
|
||||
ad.u.net.family = family;
|
||||
if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
|
||||
|
@ -4576,6 +4623,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
|
|||
struct sock *sk = skb->sk;
|
||||
struct sk_security_struct *sksec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
char *addrp;
|
||||
u8 proto;
|
||||
|
||||
|
@ -4584,6 +4632,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
|
|||
sksec = sk->sk_security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.netif = ifindex;
|
||||
ad.u.net.family = family;
|
||||
if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
|
||||
|
@ -4607,6 +4656,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
|
|||
u32 peer_sid;
|
||||
struct sock *sk;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
char *addrp;
|
||||
u8 secmark_active;
|
||||
u8 peerlbl_active;
|
||||
|
@ -4653,6 +4703,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
|
|||
}
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, NET);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.net.netif = ifindex;
|
||||
ad.u.net.family = family;
|
||||
if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
|
||||
|
@ -4769,11 +4820,13 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
|
|||
{
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
|
||||
isec = ipc_perms->security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = ipc_perms->key;
|
||||
|
||||
return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
|
||||
|
@ -4794,6 +4847,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
|
|||
{
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
int rc;
|
||||
|
||||
|
@ -4804,6 +4858,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
|
|||
isec = msq->q_perm.security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = msq->q_perm.key;
|
||||
|
||||
rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
|
||||
|
@ -4824,11 +4879,13 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
|
|||
{
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
|
||||
isec = msq->q_perm.security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = msq->q_perm.key;
|
||||
|
||||
return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
|
||||
|
@ -4868,6 +4925,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
|
|||
struct ipc_security_struct *isec;
|
||||
struct msg_security_struct *msec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
int rc;
|
||||
|
||||
|
@ -4889,6 +4947,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
|
|||
}
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = msq->q_perm.key;
|
||||
|
||||
/* Can this process write to the queue? */
|
||||
|
@ -4913,6 +4972,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
|
|||
struct ipc_security_struct *isec;
|
||||
struct msg_security_struct *msec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = task_sid(target);
|
||||
int rc;
|
||||
|
||||
|
@ -4920,6 +4980,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
|
|||
msec = msg->security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = msq->q_perm.key;
|
||||
|
||||
rc = avc_has_perm(sid, isec->sid,
|
||||
|
@ -4935,6 +4996,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
|
|||
{
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
int rc;
|
||||
|
||||
|
@ -4945,6 +5007,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
|
|||
isec = shp->shm_perm.security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = shp->shm_perm.key;
|
||||
|
||||
rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
|
||||
|
@ -4965,11 +5028,13 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
|
|||
{
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
|
||||
isec = shp->shm_perm.security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = shp->shm_perm.key;
|
||||
|
||||
return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
|
||||
|
@ -5027,6 +5092,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
|
|||
{
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
int rc;
|
||||
|
||||
|
@ -5037,6 +5103,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
|
|||
isec = sma->sem_perm.security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = sma->sem_perm.key;
|
||||
|
||||
rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
|
||||
|
@ -5057,11 +5124,13 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
|
|||
{
|
||||
struct ipc_security_struct *isec;
|
||||
struct common_audit_data ad;
|
||||
struct selinux_audit_data sad = {0,};
|
||||
u32 sid = current_sid();
|
||||
|
||||
isec = sma->sem_perm.security;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, IPC);
|
||||
ad.selinux_audit_data = &sad;
|
||||
ad.u.ipc_id = sma->sem_perm.key;
|
||||
|
||||
return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
|
||||
|
|
|
@ -46,6 +46,22 @@ struct avc_cache_stats {
|
|||
unsigned int frees;
|
||||
};
|
||||
|
||||
struct selinux_audit_data {
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
* AVC operations
|
||||
*/
|
||||
|
|
|
@ -185,6 +185,15 @@ struct smack_known {
|
|||
*/
|
||||
#define SMK_NUM_ACCESS_TYPE 5
|
||||
|
||||
/* SMACK data */
|
||||
struct smack_audit_data {
|
||||
const char *function;
|
||||
char *subject;
|
||||
char *object;
|
||||
char *request;
|
||||
int result;
|
||||
};
|
||||
|
||||
/*
|
||||
* Smack audit data; is empty if CONFIG_AUDIT not set
|
||||
* to save some stack
|
||||
|
@ -192,6 +201,7 @@ struct smack_known {
|
|||
struct smk_audit_info {
|
||||
#ifdef CONFIG_AUDIT
|
||||
struct common_audit_data a;
|
||||
struct smack_audit_data sad;
|
||||
#endif
|
||||
};
|
||||
/*
|
||||
|
@ -311,7 +321,8 @@ static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
|
|||
{
|
||||
memset(a, 0, sizeof(*a));
|
||||
a->a.type = type;
|
||||
a->a.smack_audit_data.function = func;
|
||||
a->a.smack_audit_data = &a->sad;
|
||||
a->a.smack_audit_data->function = func;
|
||||
}
|
||||
|
||||
static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
|
||||
|
|
|
@ -275,9 +275,9 @@ static inline void smack_str_from_perm(char *string, int access)
|
|||
static void smack_log_callback(struct audit_buffer *ab, void *a)
|
||||
{
|
||||
struct common_audit_data *ad = a;
|
||||
struct smack_audit_data *sad = &ad->smack_audit_data;
|
||||
struct smack_audit_data *sad = ad->smack_audit_data;
|
||||
audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
|
||||
ad->smack_audit_data.function,
|
||||
ad->smack_audit_data->function,
|
||||
sad->result ? "denied" : "granted");
|
||||
audit_log_format(ab, " subject=");
|
||||
audit_log_untrustedstring(ab, sad->subject);
|
||||
|
@ -310,11 +310,12 @@ void smack_log(char *subject_label, char *object_label, int request,
|
|||
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
|
||||
return;
|
||||
|
||||
if (a->smack_audit_data.function == NULL)
|
||||
a->smack_audit_data.function = "unknown";
|
||||
sad = a->smack_audit_data;
|
||||
|
||||
if (sad->function == NULL)
|
||||
sad->function = "unknown";
|
||||
|
||||
/* end preparing the audit data */
|
||||
sad = &a->smack_audit_data;
|
||||
smack_str_from_perm(request_buffer, request);
|
||||
sad->subject = subject_label;
|
||||
sad->object = object_label;
|
||||
|
|
Загрузка…
Ссылка в новой задаче