xref: /linux/security/lsm_audit.c (revision 5d728015)
16e837fb1SEtienne Basset /*
26e837fb1SEtienne Basset  * common LSM auditing functions
36e837fb1SEtienne Basset  *
46e837fb1SEtienne Basset  * Based on code written for SELinux by :
5*5d728015SStephen Smalley  *			Stephen Smalley, <sds@tycho.nsa.gov>
66e837fb1SEtienne Basset  * 			James Morris <jmorris@redhat.com>
76e837fb1SEtienne Basset  * Author : Etienne Basset, <etienne.basset@ensta.org>
86e837fb1SEtienne Basset  *
96e837fb1SEtienne Basset  * This program is free software; you can redistribute it and/or modify
106e837fb1SEtienne Basset  * it under the terms of the GNU General Public License version 2,
116e837fb1SEtienne Basset  * as published by the Free Software Foundation.
126e837fb1SEtienne Basset  */
136e837fb1SEtienne Basset 
146e837fb1SEtienne Basset #include <linux/types.h>
156e837fb1SEtienne Basset #include <linux/stddef.h>
166e837fb1SEtienne Basset #include <linux/kernel.h>
175a0e3ad6STejun Heo #include <linux/gfp.h>
186e837fb1SEtienne Basset #include <linux/fs.h>
196e837fb1SEtienne Basset #include <linux/init.h>
206e837fb1SEtienne Basset #include <net/sock.h>
216e837fb1SEtienne Basset #include <linux/un.h>
226e837fb1SEtienne Basset #include <net/af_unix.h>
236e837fb1SEtienne Basset #include <linux/audit.h>
246e837fb1SEtienne Basset #include <linux/ipv6.h>
256e837fb1SEtienne Basset #include <linux/ip.h>
266e837fb1SEtienne Basset #include <net/ip.h>
276e837fb1SEtienne Basset #include <net/ipv6.h>
286e837fb1SEtienne Basset #include <linux/tcp.h>
296e837fb1SEtienne Basset #include <linux/udp.h>
306e837fb1SEtienne Basset #include <linux/dccp.h>
316e837fb1SEtienne Basset #include <linux/sctp.h>
326e837fb1SEtienne Basset #include <linux/lsm_audit.h>
336e837fb1SEtienne Basset 
346e837fb1SEtienne Basset /**
356e837fb1SEtienne Basset  * ipv4_skb_to_auditdata : fill auditdata from skb
366e837fb1SEtienne Basset  * @skb : the skb
376e837fb1SEtienne Basset  * @ad : the audit data to fill
386e837fb1SEtienne Basset  * @proto : the layer 4 protocol
396e837fb1SEtienne Basset  *
406e837fb1SEtienne Basset  * return  0 on success
416e837fb1SEtienne Basset  */
426e837fb1SEtienne Basset int ipv4_skb_to_auditdata(struct sk_buff *skb,
436e837fb1SEtienne Basset 		struct common_audit_data *ad, u8 *proto)
446e837fb1SEtienne Basset {
456e837fb1SEtienne Basset 	int ret = 0;
466e837fb1SEtienne Basset 	struct iphdr *ih;
476e837fb1SEtienne Basset 
486e837fb1SEtienne Basset 	ih = ip_hdr(skb);
496e837fb1SEtienne Basset 	if (ih == NULL)
506e837fb1SEtienne Basset 		return -EINVAL;
516e837fb1SEtienne Basset 
5248c62af6SEric Paris 	ad->u.net->v4info.saddr = ih->saddr;
5348c62af6SEric Paris 	ad->u.net->v4info.daddr = ih->daddr;
546e837fb1SEtienne Basset 
556e837fb1SEtienne Basset 	if (proto)
566e837fb1SEtienne Basset 		*proto = ih->protocol;
576e837fb1SEtienne Basset 	/* non initial fragment */
586e837fb1SEtienne Basset 	if (ntohs(ih->frag_off) & IP_OFFSET)
596e837fb1SEtienne Basset 		return 0;
606e837fb1SEtienne Basset 
616e837fb1SEtienne Basset 	switch (ih->protocol) {
626e837fb1SEtienne Basset 	case IPPROTO_TCP: {
636e837fb1SEtienne Basset 		struct tcphdr *th = tcp_hdr(skb);
646e837fb1SEtienne Basset 		if (th == NULL)
656e837fb1SEtienne Basset 			break;
666e837fb1SEtienne Basset 
6748c62af6SEric Paris 		ad->u.net->sport = th->source;
6848c62af6SEric Paris 		ad->u.net->dport = th->dest;
696e837fb1SEtienne Basset 		break;
706e837fb1SEtienne Basset 	}
716e837fb1SEtienne Basset 	case IPPROTO_UDP: {
726e837fb1SEtienne Basset 		struct udphdr *uh = udp_hdr(skb);
736e837fb1SEtienne Basset 		if (uh == NULL)
746e837fb1SEtienne Basset 			break;
756e837fb1SEtienne Basset 
7648c62af6SEric Paris 		ad->u.net->sport = uh->source;
7748c62af6SEric Paris 		ad->u.net->dport = uh->dest;
786e837fb1SEtienne Basset 		break;
796e837fb1SEtienne Basset 	}
806e837fb1SEtienne Basset 	case IPPROTO_DCCP: {
816e837fb1SEtienne Basset 		struct dccp_hdr *dh = dccp_hdr(skb);
826e837fb1SEtienne Basset 		if (dh == NULL)
836e837fb1SEtienne Basset 			break;
846e837fb1SEtienne Basset 
8548c62af6SEric Paris 		ad->u.net->sport = dh->dccph_sport;
8648c62af6SEric Paris 		ad->u.net->dport = dh->dccph_dport;
876e837fb1SEtienne Basset 		break;
886e837fb1SEtienne Basset 	}
896e837fb1SEtienne Basset 	case IPPROTO_SCTP: {
906e837fb1SEtienne Basset 		struct sctphdr *sh = sctp_hdr(skb);
916e837fb1SEtienne Basset 		if (sh == NULL)
926e837fb1SEtienne Basset 			break;
9348c62af6SEric Paris 		ad->u.net->sport = sh->source;
9448c62af6SEric Paris 		ad->u.net->dport = sh->dest;
956e837fb1SEtienne Basset 		break;
966e837fb1SEtienne Basset 	}
976e837fb1SEtienne Basset 	default:
986e837fb1SEtienne Basset 		ret = -EINVAL;
996e837fb1SEtienne Basset 	}
1006e837fb1SEtienne Basset 	return ret;
1016e837fb1SEtienne Basset }
1021a93a6eaSJavier Martinez Canillas #if IS_ENABLED(CONFIG_IPV6)
1036e837fb1SEtienne Basset /**
1046e837fb1SEtienne Basset  * ipv6_skb_to_auditdata : fill auditdata from skb
1056e837fb1SEtienne Basset  * @skb : the skb
1066e837fb1SEtienne Basset  * @ad : the audit data to fill
1076e837fb1SEtienne Basset  * @proto : the layer 4 protocol
1086e837fb1SEtienne Basset  *
1096e837fb1SEtienne Basset  * return  0 on success
1106e837fb1SEtienne Basset  */
1116e837fb1SEtienne Basset int ipv6_skb_to_auditdata(struct sk_buff *skb,
1126e837fb1SEtienne Basset 		struct common_audit_data *ad, u8 *proto)
1136e837fb1SEtienne Basset {
1146e837fb1SEtienne Basset 	int offset, ret = 0;
1156e837fb1SEtienne Basset 	struct ipv6hdr *ip6;
1166e837fb1SEtienne Basset 	u8 nexthdr;
11775f2811cSJesse Gross 	__be16 frag_off;
1186e837fb1SEtienne Basset 
1196e837fb1SEtienne Basset 	ip6 = ipv6_hdr(skb);
1206e837fb1SEtienne Basset 	if (ip6 == NULL)
1216e837fb1SEtienne Basset 		return -EINVAL;
12248c62af6SEric Paris 	ad->u.net->v6info.saddr = ip6->saddr;
12348c62af6SEric Paris 	ad->u.net->v6info.daddr = ip6->daddr;
1246e837fb1SEtienne Basset 	ret = 0;
1256e837fb1SEtienne Basset 	/* IPv6 can have several extension header before the Transport header
1266e837fb1SEtienne Basset 	 * skip them */
1276e837fb1SEtienne Basset 	offset = skb_network_offset(skb);
1286e837fb1SEtienne Basset 	offset += sizeof(*ip6);
1296e837fb1SEtienne Basset 	nexthdr = ip6->nexthdr;
13075f2811cSJesse Gross 	offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
1316e837fb1SEtienne Basset 	if (offset < 0)
1326e837fb1SEtienne Basset 		return 0;
1336e837fb1SEtienne Basset 	if (proto)
1346e837fb1SEtienne Basset 		*proto = nexthdr;
1356e837fb1SEtienne Basset 	switch (nexthdr) {
1366e837fb1SEtienne Basset 	case IPPROTO_TCP: {
1376e837fb1SEtienne Basset 		struct tcphdr _tcph, *th;
1386e837fb1SEtienne Basset 
1396e837fb1SEtienne Basset 		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
1406e837fb1SEtienne Basset 		if (th == NULL)
1416e837fb1SEtienne Basset 			break;
1426e837fb1SEtienne Basset 
14348c62af6SEric Paris 		ad->u.net->sport = th->source;
14448c62af6SEric Paris 		ad->u.net->dport = th->dest;
1456e837fb1SEtienne Basset 		break;
1466e837fb1SEtienne Basset 	}
1476e837fb1SEtienne Basset 	case IPPROTO_UDP: {
1486e837fb1SEtienne Basset 		struct udphdr _udph, *uh;
1496e837fb1SEtienne Basset 
1506e837fb1SEtienne Basset 		uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
1516e837fb1SEtienne Basset 		if (uh == NULL)
1526e837fb1SEtienne Basset 			break;
1536e837fb1SEtienne Basset 
15448c62af6SEric Paris 		ad->u.net->sport = uh->source;
15548c62af6SEric Paris 		ad->u.net->dport = uh->dest;
1566e837fb1SEtienne Basset 		break;
1576e837fb1SEtienne Basset 	}
1586e837fb1SEtienne Basset 	case IPPROTO_DCCP: {
1596e837fb1SEtienne Basset 		struct dccp_hdr _dccph, *dh;
1606e837fb1SEtienne Basset 
1616e837fb1SEtienne Basset 		dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
1626e837fb1SEtienne Basset 		if (dh == NULL)
1636e837fb1SEtienne Basset 			break;
1646e837fb1SEtienne Basset 
16548c62af6SEric Paris 		ad->u.net->sport = dh->dccph_sport;
16648c62af6SEric Paris 		ad->u.net->dport = dh->dccph_dport;
1676e837fb1SEtienne Basset 		break;
1686e837fb1SEtienne Basset 	}
1696e837fb1SEtienne Basset 	case IPPROTO_SCTP: {
1706e837fb1SEtienne Basset 		struct sctphdr _sctph, *sh;
1716e837fb1SEtienne Basset 
1726e837fb1SEtienne Basset 		sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
1736e837fb1SEtienne Basset 		if (sh == NULL)
1746e837fb1SEtienne Basset 			break;
17548c62af6SEric Paris 		ad->u.net->sport = sh->source;
17648c62af6SEric Paris 		ad->u.net->dport = sh->dest;
1776e837fb1SEtienne Basset 		break;
1786e837fb1SEtienne Basset 	}
1796e837fb1SEtienne Basset 	default:
1806e837fb1SEtienne Basset 		ret = -EINVAL;
1816e837fb1SEtienne Basset 	}
1826e837fb1SEtienne Basset 	return ret;
1836e837fb1SEtienne Basset }
1846e837fb1SEtienne Basset #endif
1856e837fb1SEtienne Basset 
1866e837fb1SEtienne Basset 
1876e837fb1SEtienne Basset static inline void print_ipv6_addr(struct audit_buffer *ab,
1886e837fb1SEtienne Basset 				   struct in6_addr *addr, __be16 port,
1896e837fb1SEtienne Basset 				   char *name1, char *name2)
1906e837fb1SEtienne Basset {
1916e837fb1SEtienne Basset 	if (!ipv6_addr_any(addr))
192d8116591SPaul Moore 		audit_log_format(ab, " %s=%pI6c", name1, addr);
1936e837fb1SEtienne Basset 	if (port)
1946e837fb1SEtienne Basset 		audit_log_format(ab, " %s=%d", name2, ntohs(port));
1956e837fb1SEtienne Basset }
1966e837fb1SEtienne Basset 
1976e837fb1SEtienne Basset static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
1986e837fb1SEtienne Basset 				   __be16 port, char *name1, char *name2)
1996e837fb1SEtienne Basset {
2006e837fb1SEtienne Basset 	if (addr)
2016e837fb1SEtienne Basset 		audit_log_format(ab, " %s=%pI4", name1, &addr);
2026e837fb1SEtienne Basset 	if (port)
2036e837fb1SEtienne Basset 		audit_log_format(ab, " %s=%d", name2, ntohs(port));
2046e837fb1SEtienne Basset }
2056e837fb1SEtienne Basset 
2066e837fb1SEtienne Basset /**
2076e837fb1SEtienne Basset  * dump_common_audit_data - helper to dump common audit data
2086e837fb1SEtienne Basset  * @a : common audit data
2096e837fb1SEtienne Basset  *
2106e837fb1SEtienne Basset  */
2116e837fb1SEtienne Basset static void dump_common_audit_data(struct audit_buffer *ab,
2126e837fb1SEtienne Basset 				   struct common_audit_data *a)
2136e837fb1SEtienne Basset {
2145deeb5ceSRichard Guy Briggs 	char comm[sizeof(current->comm)];
2156e837fb1SEtienne Basset 
21607f62eb6SEric Paris 	/*
21707f62eb6SEric Paris 	 * To keep stack sizes in check force programers to notice if they
21807f62eb6SEric Paris 	 * start making this union too large!  See struct lsm_network_audit
21907f62eb6SEric Paris 	 * as an example of how to deal with large data.
22007f62eb6SEric Paris 	 */
22107f62eb6SEric Paris 	BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
22207f62eb6SEric Paris 
223fa2bea2fSPaul Moore 	audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
2245deeb5ceSRichard Guy Briggs 	audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(comm)));
2256e837fb1SEtienne Basset 
2266e837fb1SEtienne Basset 	switch (a->type) {
227cb84aa9bSEric Paris 	case LSM_AUDIT_DATA_NONE:
2282bf49690SThomas Liu 		return;
2296e837fb1SEtienne Basset 	case LSM_AUDIT_DATA_IPC:
2306e837fb1SEtienne Basset 		audit_log_format(ab, " key=%d ", a->u.ipc_id);
2316e837fb1SEtienne Basset 		break;
2326e837fb1SEtienne Basset 	case LSM_AUDIT_DATA_CAP:
2336e837fb1SEtienne Basset 		audit_log_format(ab, " capability=%d ", a->u.cap);
2346e837fb1SEtienne Basset 		break;
235f48b7399SEric Paris 	case LSM_AUDIT_DATA_PATH: {
236f48b7399SEric Paris 		struct inode *inode;
237f48b7399SEric Paris 
238f48b7399SEric Paris 		audit_log_d_path(ab, " path=", &a->u.path);
239a269434dSEric Paris 
240c6f493d6SDavid Howells 		inode = d_backing_inode(a->u.path.dentry);
24141fdc305SKees Cook 		if (inode) {
24241fdc305SKees Cook 			audit_log_format(ab, " dev=");
24341fdc305SKees Cook 			audit_log_untrustedstring(ab, inode->i_sb->s_id);
24441fdc305SKees Cook 			audit_log_format(ab, " ino=%lu", inode->i_ino);
24541fdc305SKees Cook 		}
246a269434dSEric Paris 		break;
2476e837fb1SEtienne Basset 	}
24843af5de7SVivek Goyal 	case LSM_AUDIT_DATA_FILE: {
24943af5de7SVivek Goyal 		struct inode *inode;
25043af5de7SVivek Goyal 
25143af5de7SVivek Goyal 		audit_log_d_path(ab, " path=", &a->u.file->f_path);
25243af5de7SVivek Goyal 
25343af5de7SVivek Goyal 		inode = file_inode(a->u.file);
25443af5de7SVivek Goyal 		if (inode) {
25543af5de7SVivek Goyal 			audit_log_format(ab, " dev=");
25643af5de7SVivek Goyal 			audit_log_untrustedstring(ab, inode->i_sb->s_id);
25743af5de7SVivek Goyal 			audit_log_format(ab, " ino=%lu", inode->i_ino);
25843af5de7SVivek Goyal 		}
25943af5de7SVivek Goyal 		break;
26043af5de7SVivek Goyal 	}
261671a2781SJeff Vander Stoep 	case LSM_AUDIT_DATA_IOCTL_OP: {
262671a2781SJeff Vander Stoep 		struct inode *inode;
263671a2781SJeff Vander Stoep 
264671a2781SJeff Vander Stoep 		audit_log_d_path(ab, " path=", &a->u.op->path);
265671a2781SJeff Vander Stoep 
266671a2781SJeff Vander Stoep 		inode = a->u.op->path.dentry->d_inode;
267671a2781SJeff Vander Stoep 		if (inode) {
268671a2781SJeff Vander Stoep 			audit_log_format(ab, " dev=");
269671a2781SJeff Vander Stoep 			audit_log_untrustedstring(ab, inode->i_sb->s_id);
270671a2781SJeff Vander Stoep 			audit_log_format(ab, " ino=%lu", inode->i_ino);
271671a2781SJeff Vander Stoep 		}
272671a2781SJeff Vander Stoep 
2738b31f456SWilliam Roberts 		audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
274671a2781SJeff Vander Stoep 		break;
275671a2781SJeff Vander Stoep 	}
276a269434dSEric Paris 	case LSM_AUDIT_DATA_DENTRY: {
277a269434dSEric Paris 		struct inode *inode;
278a269434dSEric Paris 
279a269434dSEric Paris 		audit_log_format(ab, " name=");
280a269434dSEric Paris 		audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
281a269434dSEric Paris 
282c6f493d6SDavid Howells 		inode = d_backing_inode(a->u.dentry);
28341fdc305SKees Cook 		if (inode) {
28441fdc305SKees Cook 			audit_log_format(ab, " dev=");
28541fdc305SKees Cook 			audit_log_untrustedstring(ab, inode->i_sb->s_id);
28641fdc305SKees Cook 			audit_log_format(ab, " ino=%lu", inode->i_ino);
28741fdc305SKees Cook 		}
288f48b7399SEric Paris 		break;
289f48b7399SEric Paris 	}
290f48b7399SEric Paris 	case LSM_AUDIT_DATA_INODE: {
2916e837fb1SEtienne Basset 		struct dentry *dentry;
292f48b7399SEric Paris 		struct inode *inode;
293f48b7399SEric Paris 
294f48b7399SEric Paris 		inode = a->u.inode;
2956e837fb1SEtienne Basset 		dentry = d_find_alias(inode);
2966e837fb1SEtienne Basset 		if (dentry) {
2976e837fb1SEtienne Basset 			audit_log_format(ab, " name=");
2986e837fb1SEtienne Basset 			audit_log_untrustedstring(ab,
2996e837fb1SEtienne Basset 					 dentry->d_name.name);
3006e837fb1SEtienne Basset 			dput(dentry);
3016e837fb1SEtienne Basset 		}
30241fdc305SKees Cook 		audit_log_format(ab, " dev=");
30341fdc305SKees Cook 		audit_log_untrustedstring(ab, inode->i_sb->s_id);
30441fdc305SKees Cook 		audit_log_format(ab, " ino=%lu", inode->i_ino);
3056e837fb1SEtienne Basset 		break;
306f48b7399SEric Paris 	}
3075deeb5ceSRichard Guy Briggs 	case LSM_AUDIT_DATA_TASK: {
3085deeb5ceSRichard Guy Briggs 		struct task_struct *tsk = a->u.tsk;
309f1dc4867SRichard Guy Briggs 		if (tsk) {
310fa2bea2fSPaul Moore 			pid_t pid = task_tgid_nr(tsk);
311f1dc4867SRichard Guy Briggs 			if (pid) {
3125deeb5ceSRichard Guy Briggs 				char comm[sizeof(tsk->comm)];
3135c5bc97eSRichard Guy Briggs 				audit_log_format(ab, " opid=%d ocomm=", pid);
3145deeb5ceSRichard Guy Briggs 				audit_log_untrustedstring(ab,
3155deeb5ceSRichard Guy Briggs 				    memcpy(comm, tsk->comm, sizeof(comm)));
3166e837fb1SEtienne Basset 			}
317f1dc4867SRichard Guy Briggs 		}
3186e837fb1SEtienne Basset 		break;
3195deeb5ceSRichard Guy Briggs 	}
3206e837fb1SEtienne Basset 	case LSM_AUDIT_DATA_NET:
32148c62af6SEric Paris 		if (a->u.net->sk) {
32248c62af6SEric Paris 			struct sock *sk = a->u.net->sk;
3236e837fb1SEtienne Basset 			struct unix_sock *u;
3246e837fb1SEtienne Basset 			int len = 0;
3256e837fb1SEtienne Basset 			char *p = NULL;
3266e837fb1SEtienne Basset 
3276e837fb1SEtienne Basset 			switch (sk->sk_family) {
3286e837fb1SEtienne Basset 			case AF_INET: {
3296e837fb1SEtienne Basset 				struct inet_sock *inet = inet_sk(sk);
3306e837fb1SEtienne Basset 
331c720c7e8SEric Dumazet 				print_ipv4_addr(ab, inet->inet_rcv_saddr,
332c720c7e8SEric Dumazet 						inet->inet_sport,
3336e837fb1SEtienne Basset 						"laddr", "lport");
334c720c7e8SEric Dumazet 				print_ipv4_addr(ab, inet->inet_daddr,
335c720c7e8SEric Dumazet 						inet->inet_dport,
3366e837fb1SEtienne Basset 						"faddr", "fport");
3376e837fb1SEtienne Basset 				break;
3386e837fb1SEtienne Basset 			}
339c2bb06dbSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
3406e837fb1SEtienne Basset 			case AF_INET6: {
3416e837fb1SEtienne Basset 				struct inet_sock *inet = inet_sk(sk);
3426e837fb1SEtienne Basset 
343efe4208fSEric Dumazet 				print_ipv6_addr(ab, &sk->sk_v6_rcv_saddr,
344c720c7e8SEric Dumazet 						inet->inet_sport,
3456e837fb1SEtienne Basset 						"laddr", "lport");
346efe4208fSEric Dumazet 				print_ipv6_addr(ab, &sk->sk_v6_daddr,
347c720c7e8SEric Dumazet 						inet->inet_dport,
3486e837fb1SEtienne Basset 						"faddr", "fport");
3496e837fb1SEtienne Basset 				break;
3506e837fb1SEtienne Basset 			}
351c2bb06dbSEric Dumazet #endif
3526e837fb1SEtienne Basset 			case AF_UNIX:
3536e837fb1SEtienne Basset 				u = unix_sk(sk);
35440ffe67dSAl Viro 				if (u->path.dentry) {
35540ffe67dSAl Viro 					audit_log_d_path(ab, " path=", &u->path);
3566e837fb1SEtienne Basset 					break;
3576e837fb1SEtienne Basset 				}
3586e837fb1SEtienne Basset 				if (!u->addr)
3596e837fb1SEtienne Basset 					break;
3606e837fb1SEtienne Basset 				len = u->addr->len-sizeof(short);
3616e837fb1SEtienne Basset 				p = &u->addr->name->sun_path[0];
3626e837fb1SEtienne Basset 				audit_log_format(ab, " path=");
3636e837fb1SEtienne Basset 				if (*p)
3646e837fb1SEtienne Basset 					audit_log_untrustedstring(ab, p);
3656e837fb1SEtienne Basset 				else
3666e837fb1SEtienne Basset 					audit_log_n_hex(ab, p, len);
3676e837fb1SEtienne Basset 				break;
3686e837fb1SEtienne Basset 			}
3696e837fb1SEtienne Basset 		}
3706e837fb1SEtienne Basset 
37148c62af6SEric Paris 		switch (a->u.net->family) {
3726e837fb1SEtienne Basset 		case AF_INET:
37348c62af6SEric Paris 			print_ipv4_addr(ab, a->u.net->v4info.saddr,
37448c62af6SEric Paris 					a->u.net->sport,
3756e837fb1SEtienne Basset 					"saddr", "src");
37648c62af6SEric Paris 			print_ipv4_addr(ab, a->u.net->v4info.daddr,
37748c62af6SEric Paris 					a->u.net->dport,
3786e837fb1SEtienne Basset 					"daddr", "dest");
3796e837fb1SEtienne Basset 			break;
3806e837fb1SEtienne Basset 		case AF_INET6:
38148c62af6SEric Paris 			print_ipv6_addr(ab, &a->u.net->v6info.saddr,
38248c62af6SEric Paris 					a->u.net->sport,
3836e837fb1SEtienne Basset 					"saddr", "src");
38448c62af6SEric Paris 			print_ipv6_addr(ab, &a->u.net->v6info.daddr,
38548c62af6SEric Paris 					a->u.net->dport,
3866e837fb1SEtienne Basset 					"daddr", "dest");
3876e837fb1SEtienne Basset 			break;
3886e837fb1SEtienne Basset 		}
38948c62af6SEric Paris 		if (a->u.net->netif > 0) {
3906e837fb1SEtienne Basset 			struct net_device *dev;
3916e837fb1SEtienne Basset 
3926e837fb1SEtienne Basset 			/* NOTE: we always use init's namespace */
39348c62af6SEric Paris 			dev = dev_get_by_index(&init_net, a->u.net->netif);
3946e837fb1SEtienne Basset 			if (dev) {
3956e837fb1SEtienne Basset 				audit_log_format(ab, " netif=%s", dev->name);
3966e837fb1SEtienne Basset 				dev_put(dev);
3976e837fb1SEtienne Basset 			}
3986e837fb1SEtienne Basset 		}
3996e837fb1SEtienne Basset 		break;
4006e837fb1SEtienne Basset #ifdef CONFIG_KEYS
4016e837fb1SEtienne Basset 	case LSM_AUDIT_DATA_KEY:
4026e837fb1SEtienne Basset 		audit_log_format(ab, " key_serial=%u", a->u.key_struct.key);
4036e837fb1SEtienne Basset 		if (a->u.key_struct.key_desc) {
4046e837fb1SEtienne Basset 			audit_log_format(ab, " key_desc=");
4056e837fb1SEtienne Basset 			audit_log_untrustedstring(ab, a->u.key_struct.key_desc);
4066e837fb1SEtienne Basset 		}
4076e837fb1SEtienne Basset 		break;
4086e837fb1SEtienne Basset #endif
409dd8dbf2eSEric Paris 	case LSM_AUDIT_DATA_KMOD:
410dd8dbf2eSEric Paris 		audit_log_format(ab, " kmod=");
411dd8dbf2eSEric Paris 		audit_log_untrustedstring(ab, a->u.kmod_name);
412dd8dbf2eSEric Paris 		break;
413cfc4d882SDaniel Jurgens 	case LSM_AUDIT_DATA_IBPKEY: {
414cfc4d882SDaniel Jurgens 		struct in6_addr sbn_pfx;
415cfc4d882SDaniel Jurgens 
416cfc4d882SDaniel Jurgens 		memset(&sbn_pfx.s6_addr, 0,
417cfc4d882SDaniel Jurgens 		       sizeof(sbn_pfx.s6_addr));
418cfc4d882SDaniel Jurgens 		memcpy(&sbn_pfx.s6_addr, &a->u.ibpkey->subnet_prefix,
419cfc4d882SDaniel Jurgens 		       sizeof(a->u.ibpkey->subnet_prefix));
420cfc4d882SDaniel Jurgens 		audit_log_format(ab, " pkey=0x%x subnet_prefix=%pI6c",
421cfc4d882SDaniel Jurgens 				 a->u.ibpkey->pkey, &sbn_pfx);
422cfc4d882SDaniel Jurgens 		break;
423cfc4d882SDaniel Jurgens 	}
424ab861dfcSDaniel Jurgens 	case LSM_AUDIT_DATA_IBENDPORT:
425ab861dfcSDaniel Jurgens 		audit_log_format(ab, " device=%s port_num=%u",
426ab861dfcSDaniel Jurgens 				 a->u.ibendport->dev_name,
427ab861dfcSDaniel Jurgens 				 a->u.ibendport->port);
428ab861dfcSDaniel Jurgens 		break;
4296e837fb1SEtienne Basset 	} /* switch (a->type) */
4306e837fb1SEtienne Basset }
4316e837fb1SEtienne Basset 
4326e837fb1SEtienne Basset /**
4336e837fb1SEtienne Basset  * common_lsm_audit - generic LSM auditing function
4346e837fb1SEtienne Basset  * @a:  auxiliary audit data
435b61c37f5SLinus Torvalds  * @pre_audit: lsm-specific pre-audit callback
436b61c37f5SLinus Torvalds  * @post_audit: lsm-specific post-audit callback
4376e837fb1SEtienne Basset  *
4386e837fb1SEtienne Basset  * setup the audit buffer for common security information
4396e837fb1SEtienne Basset  * uses callback to print LSM specific information
4406e837fb1SEtienne Basset  */
441b61c37f5SLinus Torvalds void common_lsm_audit(struct common_audit_data *a,
442b61c37f5SLinus Torvalds 	void (*pre_audit)(struct audit_buffer *, void *),
443b61c37f5SLinus Torvalds 	void (*post_audit)(struct audit_buffer *, void *))
4446e837fb1SEtienne Basset {
4456e837fb1SEtienne Basset 	struct audit_buffer *ab;
4466e837fb1SEtienne Basset 
4476e837fb1SEtienne Basset 	if (a == NULL)
4486e837fb1SEtienne Basset 		return;
4496e837fb1SEtienne Basset 	/* we use GFP_ATOMIC so we won't sleep */
450a20b62bdSRichard Guy Briggs 	ab = audit_log_start(current->audit_context, GFP_ATOMIC | __GFP_NOWARN,
451a20b62bdSRichard Guy Briggs 			     AUDIT_AVC);
4526e837fb1SEtienne Basset 
4536e837fb1SEtienne Basset 	if (ab == NULL)
4546e837fb1SEtienne Basset 		return;
4556e837fb1SEtienne Basset 
456b61c37f5SLinus Torvalds 	if (pre_audit)
457b61c37f5SLinus Torvalds 		pre_audit(ab, a);
4586e837fb1SEtienne Basset 
4596e837fb1SEtienne Basset 	dump_common_audit_data(ab, a);
4606e837fb1SEtienne Basset 
461b61c37f5SLinus Torvalds 	if (post_audit)
462b61c37f5SLinus Torvalds 		post_audit(ab, a);
4636e837fb1SEtienne Basset 
4646e837fb1SEtienne Basset 	audit_log_end(ab);
4656e837fb1SEtienne Basset }
466