Skip to content

Commit 2bf4969

Browse files
Thomas LiuJames Morris
authored andcommitted
SELinux: Convert avc_audit to use lsm_audit.h
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]>
1 parent f322abf commit 2bf4969

File tree

10 files changed

+131
-283
lines changed

10 files changed

+131
-283
lines changed

include/linux/lsm_audit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct common_audit_data {
3333
#define LSM_AUDIT_DATA_IPC 4
3434
#define LSM_AUDIT_DATA_TASK 5
3535
#define LSM_AUDIT_DATA_KEY 6
36+
#define LSM_AUDIT_NO_AUDIT 7
3637
struct task_struct *tsk;
3738
union {
3839
struct {
@@ -86,6 +87,7 @@ struct common_audit_data {
8687
u16 tclass;
8788
u32 requested;
8889
u32 audited;
90+
u32 denied;
8991
struct av_decision *avd;
9092
int result;
9193
} selinux_audit_data;

security/Makefile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ obj-$(CONFIG_SECURITYFS) += inode.o
1616
# Must precede capability.o in order to stack properly.
1717
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
1818
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
19-
ifeq ($(CONFIG_AUDIT),y)
20-
obj-$(CONFIG_SECURITY_SMACK) += lsm_audit.o
21-
endif
19+
obj-$(CONFIG_AUDIT) += lsm_audit.o
2220
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
2321
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
2422
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o

security/lsm_audit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ static void dump_common_audit_data(struct audit_buffer *ab,
220220
}
221221

222222
switch (a->type) {
223+
case LSM_AUDIT_NO_AUDIT:
224+
return;
223225
case LSM_AUDIT_DATA_IPC:
224226
audit_log_format(ab, " key=%d ", a->u.ipc_id);
225227
break;

security/selinux/avc.c

Lines changed: 41 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -492,23 +492,35 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_dec
492492
return node;
493493
}
494494

495-
static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
496-
struct in6_addr *addr, __be16 port,
497-
char *name1, char *name2)
495+
/**
496+
* avc_audit_pre_callback - SELinux specific information
497+
* will be called by generic audit code
498+
* @ab: the audit buffer
499+
* @a: audit_data
500+
*/
501+
static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
498502
{
499-
if (!ipv6_addr_any(addr))
500-
audit_log_format(ab, " %s=%pI6", name1, addr);
501-
if (port)
502-
audit_log_format(ab, " %s=%d", name2, ntohs(port));
503+
struct common_audit_data *ad = a;
504+
audit_log_format(ab, "avc: %s ",
505+
ad->selinux_audit_data.denied ? "denied" : "granted");
506+
avc_dump_av(ab, ad->selinux_audit_data.tclass,
507+
ad->selinux_audit_data.audited);
508+
audit_log_format(ab, " for ");
503509
}
504510

505-
static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
506-
__be16 port, char *name1, char *name2)
511+
/**
512+
* avc_audit_post_callback - SELinux specific information
513+
* will be called by generic audit code
514+
* @ab: the audit buffer
515+
* @a: audit_data
516+
*/
517+
static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
507518
{
508-
if (addr)
509-
audit_log_format(ab, " %s=%pI4", name1, &addr);
510-
if (port)
511-
audit_log_format(ab, " %s=%d", name2, ntohs(port));
519+
struct common_audit_data *ad = a;
520+
audit_log_format(ab, " ");
521+
avc_dump_query(ab, ad->selinux_audit_data.ssid,
522+
ad->selinux_audit_data.tsid,
523+
ad->selinux_audit_data.tclass);
512524
}
513525

514526
/**
@@ -532,13 +544,10 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
532544
*/
533545
void avc_audit(u32 ssid, u32 tsid,
534546
u16 tclass, u32 requested,
535-
struct av_decision *avd, int result, struct avc_audit_data *a)
547+
struct av_decision *avd, int result, struct common_audit_data *a)
536548
{
537-
struct task_struct *tsk = current;
538-
struct inode *inode = NULL;
549+
struct common_audit_data stack_data;
539550
u32 denied, audited;
540-
struct audit_buffer *ab;
541-
542551
denied = requested & ~avd->allowed;
543552
if (denied) {
544553
audited = denied;
@@ -551,144 +560,20 @@ void avc_audit(u32 ssid, u32 tsid,
551560
if (!(audited & avd->auditallow))
552561
return;
553562
}
554-
555-
ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
556-
if (!ab)
557-
return; /* audit_panic has been called */
558-
audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted");
559-
avc_dump_av(ab, tclass, audited);
560-
audit_log_format(ab, " for ");
561-
if (a && a->tsk)
562-
tsk = a->tsk;
563-
if (tsk && tsk->pid) {
564-
audit_log_format(ab, " pid=%d comm=", tsk->pid);
565-
audit_log_untrustedstring(ab, tsk->comm);
566-
}
567-
if (a) {
568-
switch (a->type) {
569-
case AVC_AUDIT_DATA_IPC:
570-
audit_log_format(ab, " key=%d", a->u.ipc_id);
571-
break;
572-
case AVC_AUDIT_DATA_CAP:
573-
audit_log_format(ab, " capability=%d", a->u.cap);
574-
break;
575-
case AVC_AUDIT_DATA_FS:
576-
if (a->u.fs.path.dentry) {
577-
struct dentry *dentry = a->u.fs.path.dentry;
578-
if (a->u.fs.path.mnt) {
579-
audit_log_d_path(ab, "path=",
580-
&a->u.fs.path);
581-
} else {
582-
audit_log_format(ab, " name=");
583-
audit_log_untrustedstring(ab, dentry->d_name.name);
584-
}
585-
inode = dentry->d_inode;
586-
} else if (a->u.fs.inode) {
587-
struct dentry *dentry;
588-
inode = a->u.fs.inode;
589-
dentry = d_find_alias(inode);
590-
if (dentry) {
591-
audit_log_format(ab, " name=");
592-
audit_log_untrustedstring(ab, dentry->d_name.name);
593-
dput(dentry);
594-
}
595-
}
596-
if (inode)
597-
audit_log_format(ab, " dev=%s ino=%lu",
598-
inode->i_sb->s_id,
599-
inode->i_ino);
600-
break;
601-
case AVC_AUDIT_DATA_NET:
602-
if (a->u.net.sk) {
603-
struct sock *sk = a->u.net.sk;
604-
struct unix_sock *u;
605-
int len = 0;
606-
char *p = NULL;
607-
608-
switch (sk->sk_family) {
609-
case AF_INET: {
610-
struct inet_sock *inet = inet_sk(sk);
611-
612-
avc_print_ipv4_addr(ab, inet->rcv_saddr,
613-
inet->sport,
614-
"laddr", "lport");
615-
avc_print_ipv4_addr(ab, inet->daddr,
616-
inet->dport,
617-
"faddr", "fport");
618-
break;
619-
}
620-
case AF_INET6: {
621-
struct inet_sock *inet = inet_sk(sk);
622-
struct ipv6_pinfo *inet6 = inet6_sk(sk);
623-
624-
avc_print_ipv6_addr(ab, &inet6->rcv_saddr,
625-
inet->sport,
626-
"laddr", "lport");
627-
avc_print_ipv6_addr(ab, &inet6->daddr,
628-
inet->dport,
629-
"faddr", "fport");
630-
break;
631-
}
632-
case AF_UNIX:
633-
u = unix_sk(sk);
634-
if (u->dentry) {
635-
struct path path = {
636-
.dentry = u->dentry,
637-
.mnt = u->mnt
638-
};
639-
audit_log_d_path(ab, "path=",
640-
&path);
641-
break;
642-
}
643-
if (!u->addr)
644-
break;
645-
len = u->addr->len-sizeof(short);
646-
p = &u->addr->name->sun_path[0];
647-
audit_log_format(ab, " path=");
648-
if (*p)
649-
audit_log_untrustedstring(ab, p);
650-
else
651-
audit_log_n_hex(ab, p, len);
652-
break;
653-
}
654-
}
655-
656-
switch (a->u.net.family) {
657-
case AF_INET:
658-
avc_print_ipv4_addr(ab, a->u.net.v4info.saddr,
659-
a->u.net.sport,
660-
"saddr", "src");
661-
avc_print_ipv4_addr(ab, a->u.net.v4info.daddr,
662-
a->u.net.dport,
663-
"daddr", "dest");
664-
break;
665-
case AF_INET6:
666-
avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr,
667-
a->u.net.sport,
668-
"saddr", "src");
669-
avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr,
670-
a->u.net.dport,
671-
"daddr", "dest");
672-
break;
673-
}
674-
if (a->u.net.netif > 0) {
675-
struct net_device *dev;
676-
677-
/* NOTE: we always use init's namespace */
678-
dev = dev_get_by_index(&init_net,
679-
a->u.net.netif);
680-
if (dev) {
681-
audit_log_format(ab, " netif=%s",
682-
dev->name);
683-
dev_put(dev);
684-
}
685-
}
686-
break;
687-
}
563+
if (!a) {
564+
a = &stack_data;
565+
memset(a, 0, sizeof(*a));
566+
a->type = LSM_AUDIT_NO_AUDIT;
688567
}
689-
audit_log_format(ab, " ");
690-
avc_dump_query(ab, ssid, tsid, tclass);
691-
audit_log_end(ab);
568+
a->selinux_audit_data.tclass = tclass;
569+
a->selinux_audit_data.requested = requested;
570+
a->selinux_audit_data.ssid = ssid;
571+
a->selinux_audit_data.tsid = tsid;
572+
a->selinux_audit_data.audited = audited;
573+
a->selinux_audit_data.denied = denied;
574+
a->lsm_pre_audit = avc_audit_pre_callback;
575+
a->lsm_post_audit = avc_audit_post_callback;
576+
common_lsm_audit(a);
692577
}
693578

694579
/**
@@ -956,7 +841,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
956841
* another -errno upon other errors.
957842
*/
958843
int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
959-
u32 requested, struct avc_audit_data *auditdata)
844+
u32 requested, struct common_audit_data *auditdata)
960845
{
961846
struct av_decision avd;
962847
int rc;

0 commit comments

Comments
 (0)