Commit a5149bf3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'selinux' ("struct common_audit_data" sanitizer)

Merge common_audit_data cleanup patches from Eric Paris.

This is really too late, but it's a long-overdue cleanup of the costly
wrapper functions for the security layer.

The "struct common_audit_data" is used all over in critical paths,
allocated and initialized on the stack.  And used to be much too large,
causing not only unnecessarily big stack frames but the clearing of the
(mostly useless) data was also very visible in profiles.

As a particular example, in one microbenchmark for just doing "stat()"
over files a lot, selinux_inode_permission() used 7% of the CPU time.
That's despite the fact that it doesn't actually *do* anything: it is
just a helper wrapper function in the selinux security layer.

This patch-series shrinks "struct common_audit_data" sufficiently that
code generation for these kinds of wrapper functions is improved
noticeably, and we spend much less time just initializing data that we
will never use.

The functions still get called all the time, and it still shows up at
3.5+% in my microbenchmark, but it's quite a bit lower down the list,
and much less noticeable.

* Emailed patches from Eric Paris <eparis@redhat.com>:
  lsm_audit: don't specify the audit pre/post callbacks in 'struct common_audit_data'
  SELinux: do not allocate stack space for AVC data unless needed
  SELinux: remove avd from slow_avc_audit()
  SELinux: remove avd from selinux_audit_data
  LSM: shrink the common_audit_data data union
  LSM: shrink sizeof LSM specific portion of common_audit_data
parents 3ff8f932 b61c37f5
...@@ -22,6 +22,23 @@ ...@@ -22,6 +22,23 @@
#include <linux/key.h> #include <linux/key.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
struct lsm_network_audit {
int netif;
struct sock *sk;
u16 family;
__be16 dport;
__be16 sport;
union {
struct {
__be32 daddr;
__be32 saddr;
} v4;
struct {
struct in6_addr daddr;
struct in6_addr saddr;
} v6;
} fam;
};
/* Auxiliary data to use in generating the audit record. */ /* Auxiliary data to use in generating the audit record. */
struct common_audit_data { struct common_audit_data {
...@@ -41,23 +58,7 @@ struct common_audit_data { ...@@ -41,23 +58,7 @@ struct common_audit_data {
struct path path; struct path path;
struct dentry *dentry; struct dentry *dentry;
struct inode *inode; struct inode *inode;
struct { struct lsm_network_audit *net;
int netif;
struct sock *sk;
u16 family;
__be16 dport;
__be16 sport;
union {
struct {
__be32 daddr;
__be32 saddr;
} v4;
struct {
struct in6_addr daddr;
struct in6_addr saddr;
} v6;
} fam;
} net;
int cap; int cap;
int ipc_id; int ipc_id;
struct task_struct *tsk; struct task_struct *tsk;
...@@ -72,64 +73,15 @@ struct common_audit_data { ...@@ -72,64 +73,15 @@ struct common_audit_data {
/* this union contains LSM specific data */ /* this union contains LSM specific data */
union { union {
#ifdef CONFIG_SECURITY_SMACK #ifdef CONFIG_SECURITY_SMACK
/* SMACK data */ struct smack_audit_data *smack_audit_data;
struct smack_audit_data {
const char *function;
char *subject;
char *object;
char *request;
int result;
} smack_audit_data;
#endif #endif
#ifdef CONFIG_SECURITY_SELINUX #ifdef CONFIG_SECURITY_SELINUX
/* SELinux data */ struct selinux_audit_data *selinux_audit_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;
#endif #endif
#ifdef CONFIG_SECURITY_APPARMOR #ifdef CONFIG_SECURITY_APPARMOR
struct { struct apparmor_audit_data *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;
};
} apparmor_audit_data;
#endif #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 *);
}; };
#define v4info fam.v4 #define v4info fam.v4
...@@ -146,6 +98,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, ...@@ -146,6 +98,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
{ memset((_d), 0, sizeof(struct common_audit_data)); \ { memset((_d), 0, sizeof(struct common_audit_data)); \
(_d)->type = LSM_AUDIT_DATA_##_t; } (_d)->type = LSM_AUDIT_DATA_##_t; }
void common_lsm_audit(struct common_audit_data *a); void common_lsm_audit(struct common_audit_data *a,
void (*pre_audit)(struct audit_buffer *, void *),
void (*post_audit)(struct audit_buffer *, void *));
#endif #endif
...@@ -115,23 +115,23 @@ static void audit_pre(struct audit_buffer *ab, void *ca) ...@@ -115,23 +115,23 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
if (aa_g_audit_header) { if (aa_g_audit_header) {
audit_log_format(ab, "apparmor="); 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_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_format(ab, " info=");
audit_log_string(ab, sa->aad.info); audit_log_string(ab, sa->aad->info);
if (sa->aad.error) if (sa->aad->error)
audit_log_format(ab, " error=%d", sa->aad.error); audit_log_format(ab, " error=%d", sa->aad->error);
} }
if (sa->aad.profile) { if (sa->aad->profile) {
struct aa_profile *profile = sa->aad.profile; struct aa_profile *profile = sa->aad->profile;
pid_t pid; pid_t pid;
rcu_read_lock(); rcu_read_lock();
pid = rcu_dereference(tsk->real_parent)->pid; pid = rcu_dereference(tsk->real_parent)->pid;
...@@ -145,9 +145,9 @@ static void audit_pre(struct audit_buffer *ab, void *ca) ...@@ -145,9 +145,9 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
audit_log_untrustedstring(ab, profile->base.hname); audit_log_untrustedstring(ab, profile->base.hname);
} }
if (sa->aad.name) { if (sa->aad->name) {
audit_log_format(ab, " name="); audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, sa->aad.name); audit_log_untrustedstring(ab, sa->aad->name);
} }
} }
...@@ -159,10 +159,8 @@ static void audit_pre(struct audit_buffer *ab, void *ca) ...@@ -159,10 +159,8 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
void aa_audit_msg(int type, struct common_audit_data *sa, void aa_audit_msg(int type, struct common_audit_data *sa,
void (*cb) (struct audit_buffer *, void *)) void (*cb) (struct audit_buffer *, void *))
{ {
sa->aad.type = type; sa->aad->type = type;
sa->lsm_pre_audit = audit_pre; common_lsm_audit(sa, audit_pre, cb);
sa->lsm_post_audit = cb;
common_lsm_audit(sa);
} }
/** /**
...@@ -184,7 +182,7 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, ...@@ -184,7 +182,7 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
BUG_ON(!profile); BUG_ON(!profile);
if (type == AUDIT_APPARMOR_AUTO) { if (type == AUDIT_APPARMOR_AUTO) {
if (likely(!sa->aad.error)) { if (likely(!sa->aad->error)) {
if (AUDIT_MODE(profile) != AUDIT_ALL) if (AUDIT_MODE(profile) != AUDIT_ALL)
return 0; return 0;
type = AUDIT_APPARMOR_AUDIT; type = AUDIT_APPARMOR_AUDIT;
...@@ -196,21 +194,21 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, ...@@ -196,21 +194,21 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
if (AUDIT_MODE(profile) == AUDIT_QUIET || if (AUDIT_MODE(profile) == AUDIT_QUIET ||
(type == AUDIT_APPARMOR_DENIED && (type == AUDIT_APPARMOR_DENIED &&
AUDIT_MODE(profile) == AUDIT_QUIET)) AUDIT_MODE(profile) == AUDIT_QUIET))
return sa->aad.error; return sa->aad->error;
if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
type = AUDIT_APPARMOR_KILL; type = AUDIT_APPARMOR_KILL;
if (!unconfined(profile)) if (!unconfined(profile))
sa->aad.profile = profile; sa->aad->profile = profile;
aa_audit_msg(type, sa, cb); 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); (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
if (sa->aad.type == AUDIT_APPARMOR_ALLOWED) if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
return complain_error(sa->aad.error); 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, ...@@ -64,11 +64,13 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task,
struct audit_cache *ent; struct audit_cache *ent;
int type = AUDIT_APPARMOR_AUTO; int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, CAP); COMMON_AUDIT_DATA_INIT(&sa, CAP);
sa.aad = &aad;
sa.tsk = task; sa.tsk = task;
sa.u.cap = cap; sa.u.cap = cap;
sa.aad.op = OP_CAPABLE; sa.aad->op = OP_CAPABLE;
sa.aad.error = error; sa.aad->error = error;
if (likely(!error)) { if (likely(!error)) {
/* test if auditing is being forced */ /* test if auditing is being forced */
......
...@@ -67,22 +67,22 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) ...@@ -67,22 +67,22 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
uid_t fsuid = current_fsuid(); 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_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_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, " 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_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, ...@@ -107,45 +107,47 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
{ {
int type = AUDIT_APPARMOR_AUTO; int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad.op = op, sa.aad = &aad;
sa.aad.fs.request = request; aad.op = op,
sa.aad.name = name; aad.fs.request = request;
sa.aad.fs.target = target; aad.name = name;
sa.aad.fs.ouid = ouid; aad.fs.target = target;
sa.aad.info = info; aad.fs.ouid = ouid;
sa.aad.error = error; aad.info = info;
aad.error = error;
if (likely(!sa.aad.error)) {
if (likely(!sa.aad->error)) {
u32 mask = perms->audit; u32 mask = perms->audit;
if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
mask = 0xffff; mask = 0xffff;
/* mask off perms that are not being force audited */ /* 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; return 0;
type = AUDIT_APPARMOR_AUDIT; type = AUDIT_APPARMOR_AUDIT;
} else { } else {
/* only report permissions that were denied */ /* 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; type = AUDIT_APPARMOR_KILL;
/* quiet known rejects, assumes quiet and kill do not overlap */ /* 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_NOQUIET &&
AUDIT_MODE(profile) != AUDIT_ALL) AUDIT_MODE(profile) != AUDIT_ALL)
sa.aad.fs.request &= ~perms->quiet; sa.aad->fs.request &= ~perms->quiet;
if (!sa.aad.fs.request) if (!sa.aad->fs.request)
return COMPLAIN_MODE(profile) ? 0 : sa.aad.error; 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); return aa_audit(type, profile, gfp, &sa, file_audit_cb);
} }
......
...@@ -103,7 +103,33 @@ enum aa_ops { ...@@ -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 #define aad apparmor_audit_data
void aa_audit_msg(int type, struct common_audit_data *sa, 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) ...@@ -26,7 +26,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
{ {
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
audit_log_format(ab, " target="); 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, ...@@ -41,10 +41,12 @@ static int aa_audit_ptrace(struct aa_profile *profile,
struct aa_profile *target, int error) struct aa_profile *target, int error)
{ {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad.op = OP_PTRACE; sa.aad = &aad;
sa.aad.target = target; aad.op = OP_PTRACE;
sa.aad.error = error; aad.target = target;
aad.error = error;
return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa, return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
audit_cb); audit_cb);
......
...@@ -65,8 +65,10 @@ void aa_info_message(const char *str) ...@@ -65,8 +65,10 @@ void aa_info_message(const char *str)
{ {
if (audit_enabled) { if (audit_enabled) {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad.info = str; sa.aad = &aad;
aad.info = str;
aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
} }
printk(KERN_INFO "AppArmor: %s\n", str); printk(KERN_INFO "AppArmor: %s\n", str);
......
...@@ -588,10 +588,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, ...@@ -588,10 +588,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
error = aa_setprocattr_permipc(args); error = aa_setprocattr_permipc(args);
} else { } else {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad.op = OP_SETPROCATTR; sa.aad = &aad;
sa.aad.info = name; aad.op = OP_SETPROCATTR;
sa.aad.error = -EINVAL; aad.info = name;
aad.error = -EINVAL;
return aa_audit(AUDIT_APPARMOR_DENIED, return aa_audit(AUDIT_APPARMOR_DENIED,
__aa_current_profile(), GFP_KERNEL, __aa_current_profile(), GFP_KERNEL,
&sa, NULL); &sa, NULL);
......
...@@ -964,11 +964,13 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, ...@@ -964,11 +964,13 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
int error) int error)
{ {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad.op = op; sa.aad = &aad;
sa.aad.name = name; aad.op = op;
sa.aad.info = info; aad.name = name;
sa.aad.error = error; aad.info = info;
aad.error = error;
return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp, return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
&sa, NULL); &sa, NULL);
......
...@@ -70,13 +70,13 @@ struct aa_ext { ...@@ -70,13 +70,13 @@ struct aa_ext {
static void audit_cb(struct audit_buffer *ab, void *va) static void audit_cb(struct audit_buffer *ab, void *va)
{ {
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
if (sa->aad.iface.target) { if (sa->aad->iface.target) {
struct aa_profile *name = sa->aad.iface.target; struct aa_profile *name = sa->aad->iface.target;
audit_log_format(ab, " name="); audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, name->base.hname); audit_log_untrustedstring(ab, name->base.hname);
} }
if (sa->aad.iface.pos) if (sa->aad->iface.pos)
audit_log_format(ab, " offset=%ld", 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, ...@@ -94,13 +94,15 @@ static int audit_iface(struct aa_profile *new, const char *name,
{ {
struct aa_profile *profile = __aa_current_profile(); struct aa_profile *profile = __aa_current_profile();
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad = &aad;
if (e) if (e)
sa.aad.iface.pos = e->pos - e->start; aad.iface.pos = e->pos - e->start;
sa.aad.iface.target = new; aad.iface.target = new;
sa.aad.name = name; aad.name = name;
sa.aad.info = info; aad.info = info;
sa.aad.error = error; aad.error = error;
return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa, return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
audit_cb); audit_cb);
......
...@@ -34,7 +34,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) ...@@ -34,7 +34,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
audit_log_format(ab, " rlimit=%s value=%lu", 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, ...@@ -50,12 +50,14 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource,
unsigned long value, int error) unsigned long value, int error)
{ {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad.op = OP_SETRLIMIT, sa.aad = &aad;
sa.aad.rlim.rlim = resource; aad.op = OP_SETRLIMIT,
sa.aad.rlim.max = value; aad.rlim.rlim = resource;
sa.aad.error = error; aad.rlim.max = value;
aad.error = error;
return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa, return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
audit_cb); audit_cb);
} }
......
...@@ -49,8 +49,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, ...@@ -49,8 +49,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
if (ih == NULL) if (ih == NULL)
return -EINVAL; return -EINVAL;
ad->u.net.v4info.saddr = ih->saddr; ad->u.net->v4info.saddr = ih->saddr;
ad->u.net.v4info.daddr = ih->daddr; ad->u.net->v4info.daddr = ih->daddr;
if (proto) if (proto)
*proto = ih->protocol; *proto = ih->protocol;
...@@ -64,8 +64,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, ...@@ -64,8 +64,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
if (th == NULL) if (th == NULL)
break; break;
ad->u.net.sport = th->source; ad->u.net->sport = th->source;
ad->u.net.dport = th->dest; ad->u.net->dport = th->dest;
break; break;
} }
case IPPROTO_UDP: { case IPPROTO_UDP: {
...@@ -73,8 +73,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, ...@@ -73,8 +73,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
if (uh == NULL) if (uh == NULL)
break; break;
ad->u.net.sport = uh->source; ad->u.net->sport = uh->source;
ad->u.net.dport = uh->dest; ad->u.net->dport = uh->dest;
break; break;
} }
case IPPROTO_DCCP: { case IPPROTO_DCCP: {
...@@ -82,16 +82,16 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, ...@@ -82,16 +82,16 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
if (dh == NULL) if (dh == NULL)
break; break;
ad->u.net.sport = dh->dccph_sport; ad->u.net->sport = dh->dccph_sport;
ad->u.net.dport = dh->dccph_dport; ad->u.net->dport = dh->dccph_dport;
break; break;
} }
case IPPROTO_SCTP: { case IPPROTO_SCTP: {
struct sctphdr *sh = sctp_hdr(skb); struct sctphdr *sh = sctp_hdr(skb);
if (sh == NULL) if (sh == NULL)
break; break;
ad->u.net.sport = sh->source; ad->u.net->sport = sh->source;
ad->u.net.dport = sh->dest; ad->u.net->dport = sh->dest;
break; break;
} }
default: default:
...@@ -119,8 +119,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, ...@@ -119,8 +119,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
ip6 = ipv6_hdr(skb); ip6 = ipv6_hdr(skb);
if (ip6 == NULL) if (ip6 == NULL)
return -EINVAL; return -EINVAL;
ad->u.net.v6info.saddr = ip6->saddr; ad->u.net->v6info.saddr = ip6->saddr;
ad->u.net.v6info.daddr = ip6->daddr; ad->u.net->v6info.daddr = ip6->daddr;
ret = 0; ret = 0;
/* IPv6 can have several extension header before the Transport header /* IPv6 can have several extension header before the Transport header
* skip them */ * skip them */
...@@ -140,8 +140,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, ...@@ -140,8 +140,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
if (th == NULL) if (th == NULL)
break; break;
ad->u.net.sport = th->source; ad->u.net->sport = th->source;
ad->u.net.dport = th->dest; ad->u.net->dport = th->dest;
break; break;
} }
case IPPROTO_UDP: { case IPPROTO_UDP: {
...@@ -151,8 +151,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, ...@@ -151,8 +151,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
if (uh == NULL) if (uh == NULL)
break; break;
ad->u.net.sport = uh->source; ad->u.net->sport = uh->source;
ad->u.net.dport = uh->dest; ad->u.net->dport = uh->dest;
break; break;
} }
case IPPROTO_DCCP: { case IPPROTO_DCCP: {
...@@ -162,8 +162,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, ...@@ -162,8 +162,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
if (dh == NULL) if (dh == NULL)
break; break;
ad->u.net.sport = dh->dccph_sport; ad->u.net->sport = dh->dccph_sport;
ad->u.net.dport = dh->dccph_dport; ad->u.net->dport = dh->dccph_dport;
break; break;
} }
case IPPROTO_SCTP: { case IPPROTO_SCTP: {
...@@ -172,8 +172,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, ...@@ -172,8 +172,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
if (sh == NULL) if (sh == NULL)
break; break;
ad->u.net.sport = sh->source; ad->u.net->sport = sh->source;
ad->u.net.dport = sh->dest; ad->u.net->dport = sh->dest;
break; break;
} }
default: default:
...@@ -281,8 +281,8 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -281,8 +281,8 @@ static void dump_common_audit_data(struct audit_buffer *ab,
} }
break; break;
case LSM_AUDIT_DATA_NET: case LSM_AUDIT_DATA_NET:
if (a->u.net.sk) { if (a->u.net->sk) {
struct sock *sk = a->u.net.sk; struct sock *sk = a->u.net->sk;
struct unix_sock *u; struct unix_sock *u;
int len = 0; int len = 0;
char *p = NULL; char *p = NULL;
...@@ -330,29 +330,29 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -330,29 +330,29 @@ static void dump_common_audit_data(struct audit_buffer *ab,
} }
} }
switch (a->u.net.family) { switch (a->u.net->family) {
case AF_INET: case AF_INET:
print_ipv4_addr(ab, a->u.net.v4info.saddr, print_ipv4_addr(ab, a->u.net->v4info.saddr,
a->u.net.sport, a->u.net->sport,
"saddr", "src"); "saddr", "src");
print_ipv4_addr(ab, a->u.net.v4info.daddr, print_ipv4_addr(ab, a->u.net->v4info.daddr,
a->u.net.dport, a->u.net->dport,
"daddr", "dest"); "daddr", "dest");
break; break;
case AF_INET6: case AF_INET6:
print_ipv6_addr(ab, &a->u.net.v6info.saddr, print_ipv6_addr(ab, &a->u.net->v6info.saddr,
a->u.net.sport, a->u.net->sport,
"saddr", "src"); "saddr", "src");
print_ipv6_addr(ab, &a->u.net.v6info.daddr, print_ipv6_addr(ab, &a->u.net->v6info.daddr,
a->u.net.dport, a->u.net->dport,
"daddr", "dest"); "daddr", "dest");
break; break;
} }
if (a->u.net.netif > 0) { if (a->u.net->netif > 0) {
struct net_device *dev; struct net_device *dev;
/* NOTE: we always use init's namespace */ /* NOTE: we always use init's namespace */
dev = dev_get_by_index(&init_net, a->u.net.netif); dev = dev_get_by_index(&init_net, a->u.net->netif);
if (dev) { if (dev) {
audit_log_format(ab, " netif=%s", dev->name); audit_log_format(ab, " netif=%s", dev->name);
dev_put(dev); dev_put(dev);
...@@ -378,11 +378,15 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -378,11 +378,15 @@ static void dump_common_audit_data(struct audit_buffer *ab,
/** /**
* common_lsm_audit - generic LSM auditing function * common_lsm_audit - generic LSM auditing function
* @a: auxiliary audit data * @a: auxiliary audit data
* @pre_audit: lsm-specific pre-audit callback
* @post_audit: lsm-specific post-audit callback
* *
* setup the audit buffer for common security information * setup the audit buffer for common security information
* uses callback to print LSM specific information * uses callback to print LSM specific information
*/ */
void common_lsm_audit(struct common_audit_data *a) void common_lsm_audit(struct common_audit_data *a,
void (*pre_audit)(struct audit_buffer *, void *),
void (*post_audit)(struct audit_buffer *, void *))
{ {
struct audit_buffer *ab; struct audit_buffer *ab;
...@@ -394,13 +398,13 @@ void common_lsm_audit(struct common_audit_data *a) ...@@ -394,13 +398,13 @@ void common_lsm_audit(struct common_audit_data *a)
if (ab == NULL) if (ab == NULL)
return; return;
if (a->lsm_pre_audit) if (pre_audit)
a->lsm_pre_audit(ab, a); pre_audit(ab, a);
dump_common_audit_data(ab, a); dump_common_audit_data(ab, a);
if (a->lsm_post_audit) if (post_audit)
a->lsm_post_audit(ab, a); post_audit(ab, a);
audit_log_end(ab); audit_log_end(ab);
} }
...@@ -436,9 +436,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) ...@@ -436,9 +436,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
{ {
struct common_audit_data *ad = a; struct common_audit_data *ad = a;
audit_log_format(ab, "avc: %s ", audit_log_format(ab, "avc: %s ",
ad->selinux_audit_data.denied ? "denied" : "granted"); ad->selinux_audit_data->slad->denied ? "denied" : "granted");
avc_dump_av(ab, ad->selinux_audit_data.tclass, avc_dump_av(ab, ad->selinux_audit_data->slad->tclass,
ad->selinux_audit_data.audited); ad->selinux_audit_data->slad->audited);
audit_log_format(ab, " for "); audit_log_format(ab, " for ");
} }
...@@ -452,22 +452,25 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) ...@@ -452,22 +452,25 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
{ {
struct common_audit_data *ad = a; struct common_audit_data *ad = a;
audit_log_format(ab, " "); audit_log_format(ab, " ");
avc_dump_query(ab, ad->selinux_audit_data.ssid, avc_dump_query(ab, ad->selinux_audit_data->slad->ssid,
ad->selinux_audit_data.tsid, ad->selinux_audit_data->slad->tsid,
ad->selinux_audit_data.tclass); ad->selinux_audit_data->slad->tclass);
} }
/* This is the slow part of avc audit with big stack footprint */ /* This is the slow part of avc audit with big stack footprint */
static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied, u32 requested, u32 audited, u32 denied,
struct av_decision *avd, struct common_audit_data *a, struct common_audit_data *a,
unsigned flags) unsigned flags)
{ {
struct common_audit_data stack_data; struct common_audit_data stack_data;
struct selinux_audit_data sad = {0,};
struct selinux_late_audit_data slad;
if (!a) { if (!a) {
a = &stack_data; a = &stack_data;
COMMON_AUDIT_DATA_INIT(a, NONE); COMMON_AUDIT_DATA_INIT(a, NONE);
a->selinux_audit_data = &sad;
} }
/* /*
...@@ -481,15 +484,15 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, ...@@ -481,15 +484,15 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
(flags & MAY_NOT_BLOCK)) (flags & MAY_NOT_BLOCK))
return -ECHILD; return -ECHILD;
a->selinux_audit_data.tclass = tclass; slad.tclass = tclass;
a->selinux_audit_data.requested = requested; slad.requested = requested;
a->selinux_audit_data.ssid = ssid; slad.ssid = ssid;
a->selinux_audit_data.tsid = tsid; slad.tsid = tsid;
a->selinux_audit_data.audited = audited; slad.audited = audited;
a->selinux_audit_data.denied = denied; slad.denied = denied;
a->lsm_pre_audit = avc_audit_pre_callback;
a->lsm_post_audit = avc_audit_post_callback; a->selinux_audit_data->slad = &slad;
common_lsm_audit(a); common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback);
return 0; return 0;
} }
...@@ -523,7 +526,7 @@ inline int avc_audit(u32 ssid, u32 tsid, ...@@ -523,7 +526,7 @@ inline int avc_audit(u32 ssid, u32 tsid,
if (unlikely(denied)) { if (unlikely(denied)) {
audited = denied & avd->auditdeny; 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 * this field means that ANY denials should NOT be audited if
* the policy contains an explicit dontaudit rule for that * the policy contains an explicit dontaudit rule for that
* permission. Take notice that this is unrelated to the * permission. Take notice that this is unrelated to the
...@@ -532,15 +535,15 @@ inline int avc_audit(u32 ssid, u32 tsid, ...@@ -532,15 +535,15 @@ inline int avc_audit(u32 ssid, u32 tsid,
* *
* denied == READ * denied == READ
* avd.auditdeny & ACCESS == 0 (not set means explicit rule) * 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 * We will NOT audit the denial even though the denied
* permission was READ and the auditdeny checks were for * permission was READ and the auditdeny checks were for
* ACCESS * ACCESS
*/ */
if (a && if (a &&
a->selinux_audit_data.auditdeny && a->selinux_audit_data->auditdeny &&
!(a->selinux_audit_data.auditdeny & avd->auditdeny)) !(a->selinux_audit_data->auditdeny & avd->auditdeny))
audited = 0; audited = 0;
} else if (result) } else if (result)
audited = denied = requested; audited = denied = requested;
...@@ -551,7 +554,7 @@ inline int avc_audit(u32 ssid, u32 tsid, ...@@ -551,7 +554,7 @@ inline int avc_audit(u32 ssid, u32 tsid,
return slow_avc_audit(ssid, tsid, tclass, return slow_avc_audit(ssid, tsid, tclass,
requested, audited, denied, requested, audited, denied,
avd, a, flags); a, flags);
} }
/** /**
......
...@@ -1420,6 +1420,7 @@ static int cred_has_capability(const struct cred *cred, ...@@ -1420,6 +1420,7 @@ static int cred_has_capability(const struct cred *cred,
int cap, int audit) int cap, int audit)
{ {
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct av_decision avd; struct av_decision avd;
u16 sclass; u16 sclass;
u32 sid = cred_sid(cred); u32 sid = cred_sid(cred);
...@@ -1427,6 +1428,7 @@ static int cred_has_capability(const struct cred *cred, ...@@ -1427,6 +1428,7 @@ static int cred_has_capability(const struct cred *cred,
int rc; int rc;
COMMON_AUDIT_DATA_INIT(&ad, CAP); COMMON_AUDIT_DATA_INIT(&ad, CAP);
ad.selinux_audit_data = &sad;
ad.tsk = current; ad.tsk = current;
ad.u.cap = cap; ad.u.cap = cap;
...@@ -1492,9 +1494,11 @@ static int inode_has_perm_noadp(const struct cred *cred, ...@@ -1492,9 +1494,11 @@ static int inode_has_perm_noadp(const struct cred *cred,
unsigned flags) unsigned flags)
{ {
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, INODE); COMMON_AUDIT_DATA_INIT(&ad, INODE);
ad.u.inode = inode; ad.u.inode = inode;
ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, perms, &ad, flags); return inode_has_perm(cred, inode, perms, &ad, flags);
} }
...@@ -1507,9 +1511,11 @@ static inline int dentry_has_perm(const struct cred *cred, ...@@ -1507,9 +1511,11 @@ static inline int dentry_has_perm(const struct cred *cred,
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.u.dentry = dentry; ad.u.dentry = dentry;
ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, av, &ad, 0); return inode_has_perm(cred, inode, av, &ad, 0);
} }
...@@ -1522,9 +1528,11 @@ static inline int path_has_perm(const struct cred *cred, ...@@ -1522,9 +1528,11 @@ static inline int path_has_perm(const struct cred *cred,
{ {
struct inode *inode = path->dentry->d_inode; struct inode *inode = path->dentry->d_inode;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, PATH); COMMON_AUDIT_DATA_INIT(&ad, PATH);
ad.u.path = *path; ad.u.path = *path;
ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, av, &ad, 0); return inode_has_perm(cred, inode, av, &ad, 0);
} }
...@@ -1543,11 +1551,13 @@ static int file_has_perm(const struct cred *cred, ...@@ -1543,11 +1551,13 @@ static int file_has_perm(const struct cred *cred,
struct file_security_struct *fsec = file->f_security; struct file_security_struct *fsec = file->f_security;
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = cred_sid(cred); u32 sid = cred_sid(cred);
int rc; int rc;
COMMON_AUDIT_DATA_INIT(&ad, PATH); COMMON_AUDIT_DATA_INIT(&ad, PATH);
ad.u.path = file->f_path; ad.u.path = file->f_path;
ad.selinux_audit_data = &sad;
if (sid != fsec->sid) { if (sid != fsec->sid) {
rc = avc_has_perm(sid, fsec->sid, rc = avc_has_perm(sid, fsec->sid,
...@@ -1577,6 +1587,7 @@ static int may_create(struct inode *dir, ...@@ -1577,6 +1587,7 @@ static int may_create(struct inode *dir,
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
u32 sid, newsid; u32 sid, newsid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
int rc; int rc;
dsec = dir->i_security; dsec = dir->i_security;
...@@ -1587,6 +1598,7 @@ static int may_create(struct inode *dir, ...@@ -1587,6 +1598,7 @@ static int may_create(struct inode *dir,
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.u.dentry = dentry; ad.u.dentry = dentry;
ad.selinux_audit_data = &sad;
rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
DIR__ADD_NAME | DIR__SEARCH, DIR__ADD_NAME | DIR__SEARCH,
...@@ -1631,6 +1643,7 @@ static int may_link(struct inode *dir, ...@@ -1631,6 +1643,7 @@ static int may_link(struct inode *dir,
{ {
struct inode_security_struct *dsec, *isec; struct inode_security_struct *dsec, *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
u32 av; u32 av;
int rc; int rc;
...@@ -1640,6 +1653,7 @@ static int may_link(struct inode *dir, ...@@ -1640,6 +1653,7 @@ static int may_link(struct inode *dir,
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.u.dentry = dentry; ad.u.dentry = dentry;
ad.selinux_audit_data = &sad;
av = DIR__SEARCH; av = DIR__SEARCH;
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
...@@ -1674,6 +1688,7 @@ static inline int may_rename(struct inode *old_dir, ...@@ -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 inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
u32 av; u32 av;
int old_is_dir, new_is_dir; int old_is_dir, new_is_dir;
...@@ -1685,6 +1700,7 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1685,6 +1700,7 @@ static inline int may_rename(struct inode *old_dir,
new_dsec = new_dir->i_security; new_dsec = new_dir->i_security;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.selinux_audit_data = &sad;
ad.u.dentry = old_dentry; ad.u.dentry = old_dentry;
rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
...@@ -1970,6 +1986,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) ...@@ -1970,6 +1986,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
struct task_security_struct *new_tsec; struct task_security_struct *new_tsec;
struct inode_security_struct *isec; struct inode_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct inode *inode = bprm->file->f_path.dentry->d_inode; struct inode *inode = bprm->file->f_path.dentry->d_inode;
int rc; int rc;
...@@ -2009,6 +2026,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) ...@@ -2009,6 +2026,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
} }
COMMON_AUDIT_DATA_INIT(&ad, PATH); COMMON_AUDIT_DATA_INIT(&ad, PATH);
ad.selinux_audit_data = &sad;
ad.u.path = bprm->file->f_path; ad.u.path = bprm->file->f_path;
if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
...@@ -2098,6 +2116,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, ...@@ -2098,6 +2116,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
struct files_struct *files) struct files_struct *files)
{ {
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct file *file, *devnull = NULL; struct file *file, *devnull = NULL;
struct tty_struct *tty; struct tty_struct *tty;
struct fdtable *fdt; struct fdtable *fdt;
...@@ -2135,6 +2154,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, ...@@ -2135,6 +2154,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
/* Revalidate access to inherited open files. */ /* Revalidate access to inherited open files. */
COMMON_AUDIT_DATA_INIT(&ad, INODE); COMMON_AUDIT_DATA_INIT(&ad, INODE);
ad.selinux_audit_data = &sad;
spin_lock(&files->file_lock); spin_lock(&files->file_lock);
for (;;) { for (;;) {
...@@ -2472,6 +2492,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) ...@@ -2472,6 +2492,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
int rc; int rc;
rc = superblock_doinit(sb, data); rc = superblock_doinit(sb, data);
...@@ -2483,6 +2504,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) ...@@ -2483,6 +2504,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
return 0; return 0;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.selinux_audit_data = &sad;
ad.u.dentry = sb->s_root; ad.u.dentry = sb->s_root;
return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
} }
...@@ -2491,8 +2513,10 @@ static int selinux_sb_statfs(struct dentry *dentry) ...@@ -2491,8 +2513,10 @@ static int selinux_sb_statfs(struct dentry *dentry)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.selinux_audit_data = &sad;
ad.u.dentry = dentry->d_sb->s_root; ad.u.dentry = dentry->d_sb->s_root;
return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); 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) ...@@ -2656,6 +2680,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 perms; u32 perms;
bool from_access; bool from_access;
unsigned flags = mask & MAY_NOT_BLOCK; unsigned flags = mask & MAY_NOT_BLOCK;
...@@ -2668,10 +2693,11 @@ static int selinux_inode_permission(struct inode *inode, int mask) ...@@ -2668,10 +2693,11 @@ static int selinux_inode_permission(struct inode *inode, int mask)
return 0; return 0;
COMMON_AUDIT_DATA_INIT(&ad, INODE); COMMON_AUDIT_DATA_INIT(&ad, INODE);
ad.selinux_audit_data = &sad;
ad.u.inode = inode; ad.u.inode = inode;
if (from_access) 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); perms = file_mask_to_av(inode->i_mode, mask);
...@@ -2737,6 +2763,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, ...@@ -2737,6 +2763,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
struct inode_security_struct *isec = inode->i_security; struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 newsid, sid = current_sid(); u32 newsid, sid = current_sid();
int rc = 0; int rc = 0;
...@@ -2751,6 +2778,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, ...@@ -2751,6 +2778,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
return -EPERM; return -EPERM;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.selinux_audit_data = &sad;
ad.u.dentry = dentry; ad.u.dentry = dentry;
rc = avc_has_perm(sid, isec->sid, isec->sclass, rc = avc_has_perm(sid, isec->sid, isec->sclass,
...@@ -3345,10 +3373,12 @@ static int selinux_kernel_module_request(char *kmod_name) ...@@ -3345,10 +3373,12 @@ static int selinux_kernel_module_request(char *kmod_name)
{ {
u32 sid; u32 sid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
sid = task_sid(current); sid = task_sid(current);
COMMON_AUDIT_DATA_INIT(&ad, KMOD); COMMON_AUDIT_DATA_INIT(&ad, KMOD);
ad.selinux_audit_data = &sad;
ad.u.kmod_name = kmod_name; ad.u.kmod_name = kmod_name;
return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
...@@ -3487,8 +3517,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, ...@@ -3487,8 +3517,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
if (ihlen < sizeof(_iph)) if (ihlen < sizeof(_iph))
goto out; goto out;
ad->u.net.v4info.saddr = ih->saddr; ad->u.net->v4info.saddr = ih->saddr;
ad->u.net.v4info.daddr = ih->daddr; ad->u.net->v4info.daddr = ih->daddr;
ret = 0; ret = 0;
if (proto) if (proto)
...@@ -3506,8 +3536,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, ...@@ -3506,8 +3536,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
if (th == NULL) if (th == NULL)
break; break;
ad->u.net.sport = th->source; ad->u.net->sport = th->source;
ad->u.net.dport = th->dest; ad->u.net->dport = th->dest;
break; break;
} }
...@@ -3522,8 +3552,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, ...@@ -3522,8 +3552,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
if (uh == NULL) if (uh == NULL)
break; break;
ad->u.net.sport = uh->source; ad->u.net->sport = uh->source;
ad->u.net.dport = uh->dest; ad->u.net->dport = uh->dest;
break; break;
} }
...@@ -3538,8 +3568,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, ...@@ -3538,8 +3568,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
if (dh == NULL) if (dh == NULL)
break; break;
ad->u.net.sport = dh->dccph_sport; ad->u.net->sport = dh->dccph_sport;
ad->u.net.dport = dh->dccph_dport; ad->u.net->dport = dh->dccph_dport;
break; break;
} }
...@@ -3566,8 +3596,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, ...@@ -3566,8 +3596,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
if (ip6 == NULL) if (ip6 == NULL)
goto out; goto out;
ad->u.net.v6info.saddr = ip6->saddr; ad->u.net->v6info.saddr = ip6->saddr;
ad->u.net.v6info.daddr = ip6->daddr; ad->u.net->v6info.daddr = ip6->daddr;
ret = 0; ret = 0;
nexthdr = ip6->nexthdr; nexthdr = ip6->nexthdr;
...@@ -3587,8 +3617,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, ...@@ -3587,8 +3617,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
if (th == NULL) if (th == NULL)
break; break;
ad->u.net.sport = th->source; ad->u.net->sport = th->source;
ad->u.net.dport = th->dest; ad->u.net->dport = th->dest;
break; break;
} }
...@@ -3599,8 +3629,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, ...@@ -3599,8 +3629,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
if (uh == NULL) if (uh == NULL)
break; break;
ad->u.net.sport = uh->source; ad->u.net->sport = uh->source;
ad->u.net.dport = uh->dest; ad->u.net->dport = uh->dest;
break; break;
} }
...@@ -3611,8 +3641,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, ...@@ -3611,8 +3641,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
if (dh == NULL) if (dh == NULL)
break; break;
ad->u.net.sport = dh->dccph_sport; ad->u.net->sport = dh->dccph_sport;
ad->u.net.dport = dh->dccph_dport; ad->u.net->dport = dh->dccph_dport;
break; break;
} }
...@@ -3632,13 +3662,13 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, ...@@ -3632,13 +3662,13 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
char *addrp; char *addrp;
int ret; int ret;
switch (ad->u.net.family) { switch (ad->u.net->family) {
case PF_INET: case PF_INET:
ret = selinux_parse_skb_ipv4(skb, ad, proto); ret = selinux_parse_skb_ipv4(skb, ad, proto);
if (ret) if (ret)
goto parse_error; goto parse_error;
addrp = (char *)(src ? &ad->u.net.v4info.saddr : addrp = (char *)(src ? &ad->u.net->v4info.saddr :
&ad->u.net.v4info.daddr); &ad->u.net->v4info.daddr);
goto okay; goto okay;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
...@@ -3646,8 +3676,8 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, ...@@ -3646,8 +3676,8 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
ret = selinux_parse_skb_ipv6(skb, ad, proto); ret = selinux_parse_skb_ipv6(skb, ad, proto);
if (ret) if (ret)
goto parse_error; goto parse_error;
addrp = (char *)(src ? &ad->u.net.v6info.saddr : addrp = (char *)(src ? &ad->u.net->v6info.saddr :
&ad->u.net.v6info.daddr); &ad->u.net->v6info.daddr);
goto okay; goto okay;
#endif /* IPV6 */ #endif /* IPV6 */
default: default:
...@@ -3721,13 +3751,17 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) ...@@ -3721,13 +3751,17 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
{ {
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
u32 tsid = task_sid(task); u32 tsid = task_sid(task);
if (sksec->sid == SECINITSID_KERNEL) if (sksec->sid == SECINITSID_KERNEL)
return 0; return 0;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sk = sk; ad.selinux_audit_data = &sad;
ad.u.net = &net;
ad.u.net->sk = sk;
return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
} }
...@@ -3805,6 +3839,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3805,6 +3839,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
char *addrp; char *addrp;
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
struct sockaddr_in *addr4 = NULL; struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL; struct sockaddr_in6 *addr6 = NULL;
unsigned short snum; unsigned short snum;
...@@ -3831,8 +3867,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3831,8 +3867,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (err) if (err)
goto out; goto out;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sport = htons(snum); ad.selinux_audit_data = &sad;
ad.u.net.family = family; ad.u.net = &net;
ad.u.net->sport = htons(snum);
ad.u.net->family = family;
err = avc_has_perm(sksec->sid, sid, err = avc_has_perm(sksec->sid, sid,
sksec->sclass, sksec->sclass,
SOCKET__NAME_BIND, &ad); SOCKET__NAME_BIND, &ad);
...@@ -3864,13 +3902,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3864,13 +3902,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
goto out; goto out;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sport = htons(snum); ad.selinux_audit_data = &sad;
ad.u.net.family = family; ad.u.net = &net;
ad.u.net->sport = htons(snum);
ad.u.net->family = family;
if (family == PF_INET) if (family == PF_INET)
ad.u.net.v4info.saddr = addr4->sin_addr.s_addr; ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
else else
ad.u.net.v6info.saddr = addr6->sin6_addr; ad.u.net->v6info.saddr = addr6->sin6_addr;
err = avc_has_perm(sksec->sid, sid, err = avc_has_perm(sksec->sid, sid,
sksec->sclass, node_perm, &ad); sksec->sclass, node_perm, &ad);
...@@ -3897,6 +3937,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, ...@@ -3897,6 +3937,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
if (sksec->sclass == SECCLASS_TCP_SOCKET || if (sksec->sclass == SECCLASS_TCP_SOCKET ||
sksec->sclass == SECCLASS_DCCP_SOCKET) { sksec->sclass == SECCLASS_DCCP_SOCKET) {
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
struct sockaddr_in *addr4 = NULL; struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL; struct sockaddr_in6 *addr6 = NULL;
unsigned short snum; unsigned short snum;
...@@ -3922,8 +3964,10 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, ...@@ -3922,8 +3964,10 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.dport = htons(snum); ad.selinux_audit_data = &sad;
ad.u.net.family = sk->sk_family; ad.u.net = &net;
ad.u.net->dport = htons(snum);
ad.u.net->family = sk->sk_family;
err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
if (err) if (err)
goto out; goto out;
...@@ -4012,10 +4056,14 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, ...@@ -4012,10 +4056,14 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
struct sk_security_struct *sksec_other = other->sk_security; struct sk_security_struct *sksec_other = other->sk_security;
struct sk_security_struct *sksec_new = newsk->sk_security; struct sk_security_struct *sksec_new = newsk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
int err; int err;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sk = other; ad.selinux_audit_data = &sad;
ad.u.net = &net;
ad.u.net->sk = other;
err = avc_has_perm(sksec_sock->sid, sksec_other->sid, err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
sksec_other->sclass, sksec_other->sclass,
...@@ -4042,9 +4090,13 @@ static int selinux_socket_unix_may_send(struct socket *sock, ...@@ -4042,9 +4090,13 @@ static int selinux_socket_unix_may_send(struct socket *sock,
struct sk_security_struct *ssec = sock->sk->sk_security; struct sk_security_struct *ssec = sock->sk->sk_security;
struct sk_security_struct *osec = other->sk->sk_security; struct sk_security_struct *osec = other->sk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sk = other->sk; ad.selinux_audit_data = &sad;
ad.u.net = &net;
ad.u.net->sk = other->sk;
return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
&ad); &ad);
...@@ -4080,11 +4132,15 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, ...@@ -4080,11 +4132,15 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
u32 sk_sid = sksec->sid; u32 sk_sid = sksec->sid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
char *addrp; char *addrp;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = skb->skb_iif; ad.selinux_audit_data = &sad;
ad.u.net.family = family; ad.u.net = &net;
ad.u.net->netif = skb->skb_iif;
ad.u.net->family = family;
err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
if (err) if (err)
return err; return err;
...@@ -4111,6 +4167,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -4111,6 +4167,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
u16 family = sk->sk_family; u16 family = sk->sk_family;
u32 sk_sid = sksec->sid; u32 sk_sid = sksec->sid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
char *addrp; char *addrp;
u8 secmark_active; u8 secmark_active;
u8 peerlbl_active; u8 peerlbl_active;
...@@ -4135,8 +4193,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -4135,8 +4193,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
return 0; return 0;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = skb->skb_iif; ad.selinux_audit_data = &sad;
ad.u.net.family = family; ad.u.net = &net;
ad.u.net->netif = skb->skb_iif;
ad.u.net->family = family;
err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
if (err) if (err)
return err; return err;
...@@ -4471,6 +4531,8 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, ...@@ -4471,6 +4531,8 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
char *addrp; char *addrp;
u32 peer_sid; u32 peer_sid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
u8 secmark_active; u8 secmark_active;
u8 netlbl_active; u8 netlbl_active;
u8 peerlbl_active; u8 peerlbl_active;
...@@ -4488,8 +4550,10 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, ...@@ -4488,8 +4550,10 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
return NF_DROP; return NF_DROP;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = ifindex; ad.selinux_audit_data = &sad;
ad.u.net.family = family; ad.u.net = &net;
ad.u.net->netif = ifindex;
ad.u.net->family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
return NF_DROP; return NF_DROP;
...@@ -4576,6 +4640,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, ...@@ -4576,6 +4640,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
struct sock *sk = skb->sk; struct sock *sk = skb->sk;
struct sk_security_struct *sksec; struct sk_security_struct *sksec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
char *addrp; char *addrp;
u8 proto; u8 proto;
...@@ -4584,8 +4650,10 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, ...@@ -4584,8 +4650,10 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
sksec = sk->sk_security; sksec = sk->sk_security;
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = ifindex; ad.selinux_audit_data = &sad;
ad.u.net.family = family; ad.u.net = &net;
ad.u.net->netif = ifindex;
ad.u.net->family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
return NF_DROP; return NF_DROP;
...@@ -4607,6 +4675,8 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, ...@@ -4607,6 +4675,8 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
u32 peer_sid; u32 peer_sid;
struct sock *sk; struct sock *sk;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
char *addrp; char *addrp;
u8 secmark_active; u8 secmark_active;
u8 peerlbl_active; u8 peerlbl_active;
...@@ -4653,8 +4723,10 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, ...@@ -4653,8 +4723,10 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
} }
COMMON_AUDIT_DATA_INIT(&ad, NET); COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = ifindex; ad.selinux_audit_data = &sad;
ad.u.net.family = family; ad.u.net = &net;
ad.u.net->netif = ifindex;
ad.u.net->family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
return NF_DROP; return NF_DROP;
...@@ -4769,11 +4841,13 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, ...@@ -4769,11 +4841,13 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
isec = ipc_perms->security; isec = ipc_perms->security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = ipc_perms->key; ad.u.ipc_id = ipc_perms->key;
return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
...@@ -4794,6 +4868,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) ...@@ -4794,6 +4868,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
int rc; int rc;
...@@ -4804,6 +4879,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) ...@@ -4804,6 +4879,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
isec = msq->q_perm.security; isec = msq->q_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
...@@ -4824,11 +4900,13 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) ...@@ -4824,11 +4900,13 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
isec = msq->q_perm.security; isec = msq->q_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
...@@ -4868,6 +4946,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4868,6 +4946,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct msg_security_struct *msec; struct msg_security_struct *msec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
int rc; int rc;
...@@ -4889,6 +4968,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4889,6 +4968,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
} }
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
/* Can this process write to the queue? */ /* Can this process write to the queue? */
...@@ -4913,6 +4993,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4913,6 +4993,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct msg_security_struct *msec; struct msg_security_struct *msec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = task_sid(target); u32 sid = task_sid(target);
int rc; int rc;
...@@ -4920,6 +5001,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4920,6 +5001,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
msec = msg->security; msec = msg->security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid, rc = avc_has_perm(sid, isec->sid,
...@@ -4935,6 +5017,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) ...@@ -4935,6 +5017,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
int rc; int rc;
...@@ -4945,6 +5028,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) ...@@ -4945,6 +5028,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
isec = shp->shm_perm.security; isec = shp->shm_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = shp->shm_perm.key; ad.u.ipc_id = shp->shm_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
...@@ -4965,11 +5049,13 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) ...@@ -4965,11 +5049,13 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
isec = shp->shm_perm.security; isec = shp->shm_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = shp->shm_perm.key; ad.u.ipc_id = shp->shm_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SHM, return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
...@@ -5027,6 +5113,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) ...@@ -5027,6 +5113,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
int rc; int rc;
...@@ -5037,6 +5124,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) ...@@ -5037,6 +5124,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
isec = sma->sem_perm.security; isec = sma->sem_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = sma->sem_perm.key; ad.u.ipc_id = sma->sem_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
...@@ -5057,11 +5145,13 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg) ...@@ -5057,11 +5145,13 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
isec = sma->sem_perm.security; isec = sma->sem_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.selinux_audit_data = &sad;
ad.u.ipc_id = sma->sem_perm.key; ad.u.ipc_id = sma->sem_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SEM, return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
......
...@@ -46,6 +46,31 @@ struct avc_cache_stats { ...@@ -46,6 +46,31 @@ struct avc_cache_stats {
unsigned int frees; unsigned int frees;
}; };
/*
* We only need this data after we have decided to send an audit message.
*/
struct selinux_late_audit_data {
u32 ssid;
u32 tsid;
u16 tclass;
u32 requested;
u32 audited;
u32 denied;
int result;
};
/*
* We collect this at the beginning or during an selinux security operation
*/
struct selinux_audit_data {
/*
* auditdeny is a bit tricky and unintuitive. See the
* comments in avc.c for it's meaning and usage.
*/
u32 auditdeny;
struct selinux_late_audit_data *slad;
};
/* /*
* AVC operations * AVC operations
*/ */
......
...@@ -185,6 +185,15 @@ struct smack_known { ...@@ -185,6 +185,15 @@ struct smack_known {
*/ */
#define SMK_NUM_ACCESS_TYPE 5 #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 * Smack audit data; is empty if CONFIG_AUDIT not set
* to save some stack * to save some stack
...@@ -192,6 +201,7 @@ struct smack_known { ...@@ -192,6 +201,7 @@ struct smack_known {
struct smk_audit_info { struct smk_audit_info {
#ifdef CONFIG_AUDIT #ifdef CONFIG_AUDIT
struct common_audit_data a; struct common_audit_data a;
struct smack_audit_data sad;
#endif #endif
}; };
/* /*
...@@ -311,7 +321,16 @@ static inline void smk_ad_init(struct smk_audit_info *a, const char *func, ...@@ -311,7 +321,16 @@ static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
{ {
memset(a, 0, sizeof(*a)); memset(a, 0, sizeof(*a));
a->a.type = type; 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_init_net(struct smk_audit_info *a, const char *func,
char type, struct lsm_network_audit *net)
{
smk_ad_init(a, func, type);
memset(net, 0, sizeof(*net));
a->a.u.net = net;
} }
static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
...@@ -337,7 +356,7 @@ static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a, ...@@ -337,7 +356,7 @@ static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a, static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
struct sock *sk) struct sock *sk)
{ {
a->a.u.net.sk = sk; a->a.u.net->sk = sk;
} }
#else /* no AUDIT */ #else /* no AUDIT */
......
...@@ -275,9 +275,9 @@ static inline void smack_str_from_perm(char *string, int access) ...@@ -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) static void smack_log_callback(struct audit_buffer *ab, void *a)
{ {
struct common_audit_data *ad = 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", audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
ad->smack_audit_data.function, ad->smack_audit_data->function,
sad->result ? "denied" : "granted"); sad->result ? "denied" : "granted");
audit_log_format(ab, " subject="); audit_log_format(ab, " subject=");
audit_log_untrustedstring(ab, sad->subject); audit_log_untrustedstring(ab, sad->subject);
...@@ -310,19 +310,19 @@ void smack_log(char *subject_label, char *object_label, int request, ...@@ -310,19 +310,19 @@ void smack_log(char *subject_label, char *object_label, int request,
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
return; return;
if (a->smack_audit_data.function == NULL) sad = a->smack_audit_data;
a->smack_audit_data.function = "unknown";
if (sad->function == NULL)
sad->function = "unknown";
/* end preparing the audit data */ /* end preparing the audit data */
sad = &a->smack_audit_data;
smack_str_from_perm(request_buffer, request); smack_str_from_perm(request_buffer, request);
sad->subject = subject_label; sad->subject = subject_label;
sad->object = object_label; sad->object = object_label;
sad->request = request_buffer; sad->request = request_buffer;
sad->result = result; sad->result = result;
a->lsm_pre_audit = smack_log_callback;
common_lsm_audit(a); common_lsm_audit(a, smack_log_callback, NULL);
} }
#else /* #ifdef CONFIG_AUDIT */ #else /* #ifdef CONFIG_AUDIT */
void smack_log(char *subject_label, char *object_label, int request, void smack_log(char *subject_label, char *object_label, int request,
......
...@@ -1939,16 +1939,17 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) ...@@ -1939,16 +1939,17 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
char *hostsp; char *hostsp;
struct socket_smack *ssp = sk->sk_security; struct socket_smack *ssp = sk->sk_security;
struct smk_audit_info ad; struct smk_audit_info ad;
struct lsm_network_audit net;
rcu_read_lock(); rcu_read_lock();
hostsp = smack_host_label(sap); hostsp = smack_host_label(sap);
if (hostsp != NULL) { if (hostsp != NULL) {
sk_lbl = SMACK_UNLABELED_SOCKET; sk_lbl = SMACK_UNLABELED_SOCKET;
#ifdef CONFIG_AUDIT #ifdef CONFIG_AUDIT
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
ad.a.u.net.family = sap->sin_family; ad.a.u.net->family = sap->sin_family;
ad.a.u.net.dport = sap->sin_port; ad.a.u.net->dport = sap->sin_port;
ad.a.u.net.v4info.daddr = sap->sin_addr.s_addr; ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
#endif #endif
rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad); rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad);
} else { } else {
...@@ -2808,9 +2809,10 @@ static int smack_unix_stream_connect(struct sock *sock, ...@@ -2808,9 +2809,10 @@ static int smack_unix_stream_connect(struct sock *sock,
struct socket_smack *osp = other->sk_security; struct socket_smack *osp = other->sk_security;
struct socket_smack *nsp = newsk->sk_security; struct socket_smack *nsp = newsk->sk_security;
struct smk_audit_info ad; struct smk_audit_info ad;
struct lsm_network_audit net;
int rc = 0; int rc = 0;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
smk_ad_setfield_u_net_sk(&ad, other); smk_ad_setfield_u_net_sk(&ad, other);
if (!capable(CAP_MAC_OVERRIDE)) if (!capable(CAP_MAC_OVERRIDE))
...@@ -2840,9 +2842,10 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) ...@@ -2840,9 +2842,10 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
struct socket_smack *ssp = sock->sk->sk_security; struct socket_smack *ssp = sock->sk->sk_security;
struct socket_smack *osp = other->sk->sk_security; struct socket_smack *osp = other->sk->sk_security;
struct smk_audit_info ad; struct smk_audit_info ad;
struct lsm_network_audit net;
int rc = 0; int rc = 0;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
smk_ad_setfield_u_net_sk(&ad, other->sk); smk_ad_setfield_u_net_sk(&ad, other->sk);
if (!capable(CAP_MAC_OVERRIDE)) if (!capable(CAP_MAC_OVERRIDE))
...@@ -2990,6 +2993,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -2990,6 +2993,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
char *csp; char *csp;
int rc; int rc;
struct smk_audit_info ad; struct smk_audit_info ad;
struct lsm_network_audit net;
if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
return 0; return 0;
...@@ -3007,9 +3011,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -3007,9 +3011,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
netlbl_secattr_destroy(&secattr); netlbl_secattr_destroy(&secattr);
#ifdef CONFIG_AUDIT #ifdef CONFIG_AUDIT
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
ad.a.u.net.family = sk->sk_family; ad.a.u.net->family = sk->sk_family;
ad.a.u.net.netif = skb->skb_iif; ad.a.u.net->netif = skb->skb_iif;
ipv4_skb_to_auditdata(skb, &ad.a, NULL); ipv4_skb_to_auditdata(skb, &ad.a, NULL);
#endif #endif
/* /*
...@@ -3152,6 +3156,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -3152,6 +3156,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
char *sp; char *sp;
int rc; int rc;
struct smk_audit_info ad; struct smk_audit_info ad;
struct lsm_network_audit net;
/* handle mapped IPv4 packets arriving via IPv6 sockets */ /* handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
...@@ -3166,9 +3171,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -3166,9 +3171,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
netlbl_secattr_destroy(&secattr); netlbl_secattr_destroy(&secattr);
#ifdef CONFIG_AUDIT #ifdef CONFIG_AUDIT
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
ad.a.u.net.family = family; ad.a.u.net->family = family;
ad.a.u.net.netif = skb->skb_iif; ad.a.u.net->netif = skb->skb_iif;
ipv4_skb_to_auditdata(skb, &ad.a, NULL); ipv4_skb_to_auditdata(skb, &ad.a, NULL);
#endif #endif
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment