Skip to content

Commit

Permalink
SELinux: Convert avc_audit to use lsm_audit.h
Browse files Browse the repository at this point in the history
Convert avc_audit in security/selinux/avc.c to use lsm_audit.h,
for better maintainability.

 - changed selinux to use common_audit_data instead of
    avc_audit_data
 - eliminated code in avc.c and used code from lsm_audit.h instead.

Had to add a LSM_AUDIT_NO_AUDIT to lsm_audit.h so that avc_audit
can call common_lsm_audit and do the pre and post callbacks without
doing the actual dump.  This makes it so that the patched version
behaves the same way as the unpatched version.

Also added a denied field to the selinux_audit_data private space,
once again to make it so that the patched version behaves like the
unpatched.

I've tested and confirmed that AVCs look the same before and after
this patch.

Signed-off-by: Thomas Liu <[email protected]>
Acked-by:  Stephen Smalley <[email protected]>
Signed-off-by: James Morris <[email protected]>
  • Loading branch information
Thomas Liu authored and James Morris committed Aug 16, 2009
1 parent f322abf commit 2bf4969
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 283 deletions.
2 changes: 2 additions & 0 deletions include/linux/lsm_audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_IPC 4
#define LSM_AUDIT_DATA_TASK 5
#define LSM_AUDIT_DATA_KEY 6
#define LSM_AUDIT_NO_AUDIT 7
struct task_struct *tsk;
union {
struct {
Expand Down Expand Up @@ -86,6 +87,7 @@ struct common_audit_data {
u16 tclass;
u32 requested;
u32 audited;
u32 denied;
struct av_decision *avd;
int result;
} selinux_audit_data;
Expand Down
4 changes: 1 addition & 3 deletions security/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ obj-$(CONFIG_SECURITYFS) += inode.o
# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
ifeq ($(CONFIG_AUDIT),y)
obj-$(CONFIG_SECURITY_SMACK) += lsm_audit.o
endif
obj-$(CONFIG_AUDIT) += lsm_audit.o
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
Expand Down
2 changes: 2 additions & 0 deletions security/lsm_audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ static void dump_common_audit_data(struct audit_buffer *ab,
}

switch (a->type) {
case LSM_AUDIT_NO_AUDIT:
return;
case LSM_AUDIT_DATA_IPC:
audit_log_format(ab, " key=%d ", a->u.ipc_id);
break;
Expand Down
197 changes: 41 additions & 156 deletions security/selinux/avc.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,23 +492,35 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_dec
return node;
}

static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
struct in6_addr *addr, __be16 port,
char *name1, char *name2)
/**
* avc_audit_pre_callback - SELinux specific information
* will be called by generic audit code
* @ab: the audit buffer
* @a: audit_data
*/
static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
{
if (!ipv6_addr_any(addr))
audit_log_format(ab, " %s=%pI6", name1, addr);
if (port)
audit_log_format(ab, " %s=%d", name2, ntohs(port));
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);
audit_log_format(ab, " for ");
}

static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
__be16 port, char *name1, char *name2)
/**
* avc_audit_post_callback - SELinux specific information
* will be called by generic audit code
* @ab: the audit buffer
* @a: audit_data
*/
static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
{
if (addr)
audit_log_format(ab, " %s=%pI4", name1, &addr);
if (port)
audit_log_format(ab, " %s=%d", name2, ntohs(port));
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);
}

/**
Expand All @@ -532,13 +544,10 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
*/
void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *a)
struct av_decision *avd, int result, struct common_audit_data *a)
{
struct task_struct *tsk = current;
struct inode *inode = NULL;
struct common_audit_data stack_data;
u32 denied, audited;
struct audit_buffer *ab;

denied = requested & ~avd->allowed;
if (denied) {
audited = denied;
Expand All @@ -551,144 +560,20 @@ void avc_audit(u32 ssid, u32 tsid,
if (!(audited & avd->auditallow))
return;
}

ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
if (!ab)
return; /* audit_panic has been called */
audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted");
avc_dump_av(ab, tclass, audited);
audit_log_format(ab, " for ");
if (a && a->tsk)
tsk = a->tsk;
if (tsk && tsk->pid) {
audit_log_format(ab, " pid=%d comm=", tsk->pid);
audit_log_untrustedstring(ab, tsk->comm);
}
if (a) {
switch (a->type) {
case AVC_AUDIT_DATA_IPC:
audit_log_format(ab, " key=%d", a->u.ipc_id);
break;
case AVC_AUDIT_DATA_CAP:
audit_log_format(ab, " capability=%d", a->u.cap);
break;
case AVC_AUDIT_DATA_FS:
if (a->u.fs.path.dentry) {
struct dentry *dentry = a->u.fs.path.dentry;
if (a->u.fs.path.mnt) {
audit_log_d_path(ab, "path=",
&a->u.fs.path);
} else {
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, dentry->d_name.name);
}
inode = dentry->d_inode;
} else if (a->u.fs.inode) {
struct dentry *dentry;
inode = a->u.fs.inode;
dentry = d_find_alias(inode);
if (dentry) {
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, dentry->d_name.name);
dput(dentry);
}
}
if (inode)
audit_log_format(ab, " dev=%s ino=%lu",
inode->i_sb->s_id,
inode->i_ino);
break;
case AVC_AUDIT_DATA_NET:
if (a->u.net.sk) {
struct sock *sk = a->u.net.sk;
struct unix_sock *u;
int len = 0;
char *p = NULL;

switch (sk->sk_family) {
case AF_INET: {
struct inet_sock *inet = inet_sk(sk);

avc_print_ipv4_addr(ab, inet->rcv_saddr,
inet->sport,
"laddr", "lport");
avc_print_ipv4_addr(ab, inet->daddr,
inet->dport,
"faddr", "fport");
break;
}
case AF_INET6: {
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *inet6 = inet6_sk(sk);

avc_print_ipv6_addr(ab, &inet6->rcv_saddr,
inet->sport,
"laddr", "lport");
avc_print_ipv6_addr(ab, &inet6->daddr,
inet->dport,
"faddr", "fport");
break;
}
case AF_UNIX:
u = unix_sk(sk);
if (u->dentry) {
struct path path = {
.dentry = u->dentry,
.mnt = u->mnt
};
audit_log_d_path(ab, "path=",
&path);
break;
}
if (!u->addr)
break;
len = u->addr->len-sizeof(short);
p = &u->addr->name->sun_path[0];
audit_log_format(ab, " path=");
if (*p)
audit_log_untrustedstring(ab, p);
else
audit_log_n_hex(ab, p, len);
break;
}
}

switch (a->u.net.family) {
case AF_INET:
avc_print_ipv4_addr(ab, a->u.net.v4info.saddr,
a->u.net.sport,
"saddr", "src");
avc_print_ipv4_addr(ab, a->u.net.v4info.daddr,
a->u.net.dport,
"daddr", "dest");
break;
case AF_INET6:
avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr,
a->u.net.sport,
"saddr", "src");
avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr,
a->u.net.dport,
"daddr", "dest");
break;
}
if (a->u.net.netif > 0) {
struct net_device *dev;

/* NOTE: we always use init's namespace */
dev = dev_get_by_index(&init_net,
a->u.net.netif);
if (dev) {
audit_log_format(ab, " netif=%s",
dev->name);
dev_put(dev);
}
}
break;
}
if (!a) {
a = &stack_data;
memset(a, 0, sizeof(*a));
a->type = LSM_AUDIT_NO_AUDIT;
}
audit_log_format(ab, " ");
avc_dump_query(ab, ssid, tsid, tclass);
audit_log_end(ab);
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);
}

/**
Expand Down Expand Up @@ -956,7 +841,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
* another -errno upon other errors.
*/
int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct avc_audit_data *auditdata)
u32 requested, struct common_audit_data *auditdata)
{
struct av_decision avd;
int rc;
Expand Down
Loading

0 comments on commit 2bf4969

Please sign in to comment.