cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lsm_audit.c (11226B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * common LSM auditing functions
      4 *
      5 * Based on code written for SELinux by :
      6 *			Stephen Smalley, <sds@tycho.nsa.gov>
      7 * 			James Morris <jmorris@redhat.com>
      8 * Author : Etienne Basset, <etienne.basset@ensta.org>
      9 */
     10
     11#include <linux/types.h>
     12#include <linux/stddef.h>
     13#include <linux/kernel.h>
     14#include <linux/gfp.h>
     15#include <linux/fs.h>
     16#include <linux/init.h>
     17#include <net/sock.h>
     18#include <linux/un.h>
     19#include <net/af_unix.h>
     20#include <linux/audit.h>
     21#include <linux/ipv6.h>
     22#include <linux/ip.h>
     23#include <net/ip.h>
     24#include <net/ipv6.h>
     25#include <linux/tcp.h>
     26#include <linux/udp.h>
     27#include <linux/dccp.h>
     28#include <linux/sctp.h>
     29#include <linux/lsm_audit.h>
     30#include <linux/security.h>
     31
     32/**
     33 * ipv4_skb_to_auditdata : fill auditdata from skb
     34 * @skb : the skb
     35 * @ad : the audit data to fill
     36 * @proto : the layer 4 protocol
     37 *
     38 * return  0 on success
     39 */
     40int ipv4_skb_to_auditdata(struct sk_buff *skb,
     41		struct common_audit_data *ad, u8 *proto)
     42{
     43	int ret = 0;
     44	struct iphdr *ih;
     45
     46	ih = ip_hdr(skb);
     47	if (ih == NULL)
     48		return -EINVAL;
     49
     50	ad->u.net->v4info.saddr = ih->saddr;
     51	ad->u.net->v4info.daddr = ih->daddr;
     52
     53	if (proto)
     54		*proto = ih->protocol;
     55	/* non initial fragment */
     56	if (ntohs(ih->frag_off) & IP_OFFSET)
     57		return 0;
     58
     59	switch (ih->protocol) {
     60	case IPPROTO_TCP: {
     61		struct tcphdr *th = tcp_hdr(skb);
     62		if (th == NULL)
     63			break;
     64
     65		ad->u.net->sport = th->source;
     66		ad->u.net->dport = th->dest;
     67		break;
     68	}
     69	case IPPROTO_UDP: {
     70		struct udphdr *uh = udp_hdr(skb);
     71		if (uh == NULL)
     72			break;
     73
     74		ad->u.net->sport = uh->source;
     75		ad->u.net->dport = uh->dest;
     76		break;
     77	}
     78	case IPPROTO_DCCP: {
     79		struct dccp_hdr *dh = dccp_hdr(skb);
     80		if (dh == NULL)
     81			break;
     82
     83		ad->u.net->sport = dh->dccph_sport;
     84		ad->u.net->dport = dh->dccph_dport;
     85		break;
     86	}
     87	case IPPROTO_SCTP: {
     88		struct sctphdr *sh = sctp_hdr(skb);
     89		if (sh == NULL)
     90			break;
     91		ad->u.net->sport = sh->source;
     92		ad->u.net->dport = sh->dest;
     93		break;
     94	}
     95	default:
     96		ret = -EINVAL;
     97	}
     98	return ret;
     99}
    100#if IS_ENABLED(CONFIG_IPV6)
    101/**
    102 * ipv6_skb_to_auditdata : fill auditdata from skb
    103 * @skb : the skb
    104 * @ad : the audit data to fill
    105 * @proto : the layer 4 protocol
    106 *
    107 * return  0 on success
    108 */
    109int ipv6_skb_to_auditdata(struct sk_buff *skb,
    110		struct common_audit_data *ad, u8 *proto)
    111{
    112	int offset, ret = 0;
    113	struct ipv6hdr *ip6;
    114	u8 nexthdr;
    115	__be16 frag_off;
    116
    117	ip6 = ipv6_hdr(skb);
    118	if (ip6 == NULL)
    119		return -EINVAL;
    120	ad->u.net->v6info.saddr = ip6->saddr;
    121	ad->u.net->v6info.daddr = ip6->daddr;
    122	/* IPv6 can have several extension header before the Transport header
    123	 * skip them */
    124	offset = skb_network_offset(skb);
    125	offset += sizeof(*ip6);
    126	nexthdr = ip6->nexthdr;
    127	offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
    128	if (offset < 0)
    129		return 0;
    130	if (proto)
    131		*proto = nexthdr;
    132	switch (nexthdr) {
    133	case IPPROTO_TCP: {
    134		struct tcphdr _tcph, *th;
    135
    136		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
    137		if (th == NULL)
    138			break;
    139
    140		ad->u.net->sport = th->source;
    141		ad->u.net->dport = th->dest;
    142		break;
    143	}
    144	case IPPROTO_UDP: {
    145		struct udphdr _udph, *uh;
    146
    147		uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
    148		if (uh == NULL)
    149			break;
    150
    151		ad->u.net->sport = uh->source;
    152		ad->u.net->dport = uh->dest;
    153		break;
    154	}
    155	case IPPROTO_DCCP: {
    156		struct dccp_hdr _dccph, *dh;
    157
    158		dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
    159		if (dh == NULL)
    160			break;
    161
    162		ad->u.net->sport = dh->dccph_sport;
    163		ad->u.net->dport = dh->dccph_dport;
    164		break;
    165	}
    166	case IPPROTO_SCTP: {
    167		struct sctphdr _sctph, *sh;
    168
    169		sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
    170		if (sh == NULL)
    171			break;
    172		ad->u.net->sport = sh->source;
    173		ad->u.net->dport = sh->dest;
    174		break;
    175	}
    176	default:
    177		ret = -EINVAL;
    178	}
    179	return ret;
    180}
    181#endif
    182
    183
    184static inline void print_ipv6_addr(struct audit_buffer *ab,
    185				   const struct in6_addr *addr, __be16 port,
    186				   char *name1, char *name2)
    187{
    188	if (!ipv6_addr_any(addr))
    189		audit_log_format(ab, " %s=%pI6c", name1, addr);
    190	if (port)
    191		audit_log_format(ab, " %s=%d", name2, ntohs(port));
    192}
    193
    194static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
    195				   __be16 port, char *name1, char *name2)
    196{
    197	if (addr)
    198		audit_log_format(ab, " %s=%pI4", name1, &addr);
    199	if (port)
    200		audit_log_format(ab, " %s=%d", name2, ntohs(port));
    201}
    202
    203/**
    204 * dump_common_audit_data - helper to dump common audit data
    205 * @a : common audit data
    206 *
    207 */
    208static void dump_common_audit_data(struct audit_buffer *ab,
    209				   struct common_audit_data *a)
    210{
    211	char comm[sizeof(current->comm)];
    212
    213	/*
    214	 * To keep stack sizes in check force programers to notice if they
    215	 * start making this union too large!  See struct lsm_network_audit
    216	 * as an example of how to deal with large data.
    217	 */
    218	BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
    219
    220	audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
    221	audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(comm)));
    222
    223	switch (a->type) {
    224	case LSM_AUDIT_DATA_NONE:
    225		return;
    226	case LSM_AUDIT_DATA_IPC:
    227		audit_log_format(ab, " ipc_key=%d ", a->u.ipc_id);
    228		break;
    229	case LSM_AUDIT_DATA_CAP:
    230		audit_log_format(ab, " capability=%d ", a->u.cap);
    231		break;
    232	case LSM_AUDIT_DATA_PATH: {
    233		struct inode *inode;
    234
    235		audit_log_d_path(ab, " path=", &a->u.path);
    236
    237		inode = d_backing_inode(a->u.path.dentry);
    238		if (inode) {
    239			audit_log_format(ab, " dev=");
    240			audit_log_untrustedstring(ab, inode->i_sb->s_id);
    241			audit_log_format(ab, " ino=%lu", inode->i_ino);
    242		}
    243		break;
    244	}
    245	case LSM_AUDIT_DATA_FILE: {
    246		struct inode *inode;
    247
    248		audit_log_d_path(ab, " path=", &a->u.file->f_path);
    249
    250		inode = file_inode(a->u.file);
    251		if (inode) {
    252			audit_log_format(ab, " dev=");
    253			audit_log_untrustedstring(ab, inode->i_sb->s_id);
    254			audit_log_format(ab, " ino=%lu", inode->i_ino);
    255		}
    256		break;
    257	}
    258	case LSM_AUDIT_DATA_IOCTL_OP: {
    259		struct inode *inode;
    260
    261		audit_log_d_path(ab, " path=", &a->u.op->path);
    262
    263		inode = a->u.op->path.dentry->d_inode;
    264		if (inode) {
    265			audit_log_format(ab, " dev=");
    266			audit_log_untrustedstring(ab, inode->i_sb->s_id);
    267			audit_log_format(ab, " ino=%lu", inode->i_ino);
    268		}
    269
    270		audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
    271		break;
    272	}
    273	case LSM_AUDIT_DATA_DENTRY: {
    274		struct inode *inode;
    275
    276		audit_log_format(ab, " name=");
    277		spin_lock(&a->u.dentry->d_lock);
    278		audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
    279		spin_unlock(&a->u.dentry->d_lock);
    280
    281		inode = d_backing_inode(a->u.dentry);
    282		if (inode) {
    283			audit_log_format(ab, " dev=");
    284			audit_log_untrustedstring(ab, inode->i_sb->s_id);
    285			audit_log_format(ab, " ino=%lu", inode->i_ino);
    286		}
    287		break;
    288	}
    289	case LSM_AUDIT_DATA_INODE: {
    290		struct dentry *dentry;
    291		struct inode *inode;
    292
    293		rcu_read_lock();
    294		inode = a->u.inode;
    295		dentry = d_find_alias_rcu(inode);
    296		if (dentry) {
    297			audit_log_format(ab, " name=");
    298			spin_lock(&dentry->d_lock);
    299			audit_log_untrustedstring(ab, dentry->d_name.name);
    300			spin_unlock(&dentry->d_lock);
    301		}
    302		audit_log_format(ab, " dev=");
    303		audit_log_untrustedstring(ab, inode->i_sb->s_id);
    304		audit_log_format(ab, " ino=%lu", inode->i_ino);
    305		rcu_read_unlock();
    306		break;
    307	}
    308	case LSM_AUDIT_DATA_TASK: {
    309		struct task_struct *tsk = a->u.tsk;
    310		if (tsk) {
    311			pid_t pid = task_tgid_nr(tsk);
    312			if (pid) {
    313				char comm[sizeof(tsk->comm)];
    314				audit_log_format(ab, " opid=%d ocomm=", pid);
    315				audit_log_untrustedstring(ab,
    316				    memcpy(comm, tsk->comm, sizeof(comm)));
    317			}
    318		}
    319		break;
    320	}
    321	case LSM_AUDIT_DATA_NET:
    322		if (a->u.net->sk) {
    323			const struct sock *sk = a->u.net->sk;
    324			struct unix_sock *u;
    325			struct unix_address *addr;
    326			int len = 0;
    327			char *p = NULL;
    328
    329			switch (sk->sk_family) {
    330			case AF_INET: {
    331				struct inet_sock *inet = inet_sk(sk);
    332
    333				print_ipv4_addr(ab, inet->inet_rcv_saddr,
    334						inet->inet_sport,
    335						"laddr", "lport");
    336				print_ipv4_addr(ab, inet->inet_daddr,
    337						inet->inet_dport,
    338						"faddr", "fport");
    339				break;
    340			}
    341#if IS_ENABLED(CONFIG_IPV6)
    342			case AF_INET6: {
    343				struct inet_sock *inet = inet_sk(sk);
    344
    345				print_ipv6_addr(ab, &sk->sk_v6_rcv_saddr,
    346						inet->inet_sport,
    347						"laddr", "lport");
    348				print_ipv6_addr(ab, &sk->sk_v6_daddr,
    349						inet->inet_dport,
    350						"faddr", "fport");
    351				break;
    352			}
    353#endif
    354			case AF_UNIX:
    355				u = unix_sk(sk);
    356				addr = smp_load_acquire(&u->addr);
    357				if (!addr)
    358					break;
    359				if (u->path.dentry) {
    360					audit_log_d_path(ab, " path=", &u->path);
    361					break;
    362				}
    363				len = addr->len-sizeof(short);
    364				p = &addr->name->sun_path[0];
    365				audit_log_format(ab, " path=");
    366				if (*p)
    367					audit_log_untrustedstring(ab, p);
    368				else
    369					audit_log_n_hex(ab, p, len);
    370				break;
    371			}
    372		}
    373
    374		switch (a->u.net->family) {
    375		case AF_INET:
    376			print_ipv4_addr(ab, a->u.net->v4info.saddr,
    377					a->u.net->sport,
    378					"saddr", "src");
    379			print_ipv4_addr(ab, a->u.net->v4info.daddr,
    380					a->u.net->dport,
    381					"daddr", "dest");
    382			break;
    383		case AF_INET6:
    384			print_ipv6_addr(ab, &a->u.net->v6info.saddr,
    385					a->u.net->sport,
    386					"saddr", "src");
    387			print_ipv6_addr(ab, &a->u.net->v6info.daddr,
    388					a->u.net->dport,
    389					"daddr", "dest");
    390			break;
    391		}
    392		if (a->u.net->netif > 0) {
    393			struct net_device *dev;
    394
    395			/* NOTE: we always use init's namespace */
    396			dev = dev_get_by_index(&init_net, a->u.net->netif);
    397			if (dev) {
    398				audit_log_format(ab, " netif=%s", dev->name);
    399				dev_put(dev);
    400			}
    401		}
    402		break;
    403#ifdef CONFIG_KEYS
    404	case LSM_AUDIT_DATA_KEY:
    405		audit_log_format(ab, " key_serial=%u", a->u.key_struct.key);
    406		if (a->u.key_struct.key_desc) {
    407			audit_log_format(ab, " key_desc=");
    408			audit_log_untrustedstring(ab, a->u.key_struct.key_desc);
    409		}
    410		break;
    411#endif
    412	case LSM_AUDIT_DATA_KMOD:
    413		audit_log_format(ab, " kmod=");
    414		audit_log_untrustedstring(ab, a->u.kmod_name);
    415		break;
    416	case LSM_AUDIT_DATA_IBPKEY: {
    417		struct in6_addr sbn_pfx;
    418
    419		memset(&sbn_pfx.s6_addr, 0,
    420		       sizeof(sbn_pfx.s6_addr));
    421		memcpy(&sbn_pfx.s6_addr, &a->u.ibpkey->subnet_prefix,
    422		       sizeof(a->u.ibpkey->subnet_prefix));
    423		audit_log_format(ab, " pkey=0x%x subnet_prefix=%pI6c",
    424				 a->u.ibpkey->pkey, &sbn_pfx);
    425		break;
    426	}
    427	case LSM_AUDIT_DATA_IBENDPORT:
    428		audit_log_format(ab, " device=%s port_num=%u",
    429				 a->u.ibendport->dev_name,
    430				 a->u.ibendport->port);
    431		break;
    432	case LSM_AUDIT_DATA_LOCKDOWN:
    433		audit_log_format(ab, " lockdown_reason=\"%s\"",
    434				 lockdown_reasons[a->u.reason]);
    435		break;
    436	case LSM_AUDIT_DATA_ANONINODE:
    437		audit_log_format(ab, " anonclass=%s", a->u.anonclass);
    438		break;
    439	} /* switch (a->type) */
    440}
    441
    442/**
    443 * common_lsm_audit - generic LSM auditing function
    444 * @a:  auxiliary audit data
    445 * @pre_audit: lsm-specific pre-audit callback
    446 * @post_audit: lsm-specific post-audit callback
    447 *
    448 * setup the audit buffer for common security information
    449 * uses callback to print LSM specific information
    450 */
    451void common_lsm_audit(struct common_audit_data *a,
    452	void (*pre_audit)(struct audit_buffer *, void *),
    453	void (*post_audit)(struct audit_buffer *, void *))
    454{
    455	struct audit_buffer *ab;
    456
    457	if (a == NULL)
    458		return;
    459	/* we use GFP_ATOMIC so we won't sleep */
    460	ab = audit_log_start(audit_context(), GFP_ATOMIC | __GFP_NOWARN,
    461			     AUDIT_AVC);
    462
    463	if (ab == NULL)
    464		return;
    465
    466	if (pre_audit)
    467		pre_audit(ab, a);
    468
    469	dump_common_audit_data(ab, a);
    470
    471	if (post_audit)
    472		post_audit(ab, a);
    473
    474	audit_log_end(ab);
    475}