lsm_audit.c 10.6 KB
Newer Older
1 2 3 4
/*
 * common LSM auditing functions
 *
 * Based on code written for SELinux by :
5
 *			Stephen Smalley, <sds@tycho.nsa.gov>
6 7 8 9 10 11 12 13 14 15 16
 * 			James Morris <jmorris@redhat.com>
 * Author : Etienne Basset, <etienne.basset@ensta.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2,
 * as published by the Free Software Foundation.
 */

#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
17
#include <linux/gfp.h>
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
#include <linux/fs.h>
#include <linux/init.h>
#include <net/sock.h>
#include <linux/un.h>
#include <net/af_unix.h>
#include <linux/audit.h>
#include <linux/ipv6.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/dccp.h>
#include <linux/sctp.h>
#include <linux/lsm_audit.h>

/**
 * ipv4_skb_to_auditdata : fill auditdata from skb
 * @skb : the skb
 * @ad : the audit data to fill
 * @proto : the layer 4 protocol
 *
 * return  0 on success
 */
int ipv4_skb_to_auditdata(struct sk_buff *skb,
		struct common_audit_data *ad, u8 *proto)
{
	int ret = 0;
	struct iphdr *ih;

	ih = ip_hdr(skb);
	if (ih == NULL)
		return -EINVAL;

52 53
	ad->u.net->v4info.saddr = ih->saddr;
	ad->u.net->v4info.daddr = ih->daddr;
54 55 56 57 58 59 60 61 62 63 64 65 66

	if (proto)
		*proto = ih->protocol;
	/* non initial fragment */
	if (ntohs(ih->frag_off) & IP_OFFSET)
		return 0;

	switch (ih->protocol) {
	case IPPROTO_TCP: {
		struct tcphdr *th = tcp_hdr(skb);
		if (th == NULL)
			break;

67 68
		ad->u.net->sport = th->source;
		ad->u.net->dport = th->dest;
69 70 71 72 73 74 75
		break;
	}
	case IPPROTO_UDP: {
		struct udphdr *uh = udp_hdr(skb);
		if (uh == NULL)
			break;

76 77
		ad->u.net->sport = uh->source;
		ad->u.net->dport = uh->dest;
78 79 80 81 82 83 84
		break;
	}
	case IPPROTO_DCCP: {
		struct dccp_hdr *dh = dccp_hdr(skb);
		if (dh == NULL)
			break;

85 86
		ad->u.net->sport = dh->dccph_sport;
		ad->u.net->dport = dh->dccph_dport;
87 88 89 90 91 92
		break;
	}
	case IPPROTO_SCTP: {
		struct sctphdr *sh = sctp_hdr(skb);
		if (sh == NULL)
			break;
93 94
		ad->u.net->sport = sh->source;
		ad->u.net->dport = sh->dest;
95 96 97 98 99 100 101
		break;
	}
	default:
		ret = -EINVAL;
	}
	return ret;
}
102
#if IS_ENABLED(CONFIG_IPV6)
103 104 105 106 107 108 109 110 111 112 113 114 115 116
/**
 * ipv6_skb_to_auditdata : fill auditdata from skb
 * @skb : the skb
 * @ad : the audit data to fill
 * @proto : the layer 4 protocol
 *
 * return  0 on success
 */
int ipv6_skb_to_auditdata(struct sk_buff *skb,
		struct common_audit_data *ad, u8 *proto)
{
	int offset, ret = 0;
	struct ipv6hdr *ip6;
	u8 nexthdr;
117
	__be16 frag_off;
118 119 120 121

	ip6 = ipv6_hdr(skb);
	if (ip6 == NULL)
		return -EINVAL;
122 123
	ad->u.net->v6info.saddr = ip6->saddr;
	ad->u.net->v6info.daddr = ip6->daddr;
124 125 126 127 128 129
	ret = 0;
	/* IPv6 can have several extension header before the Transport header
	 * skip them */
	offset = skb_network_offset(skb);
	offset += sizeof(*ip6);
	nexthdr = ip6->nexthdr;
130
	offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
131 132 133 134 135 136 137 138 139 140 141 142
	if (offset < 0)
		return 0;
	if (proto)
		*proto = nexthdr;
	switch (nexthdr) {
	case IPPROTO_TCP: {
		struct tcphdr _tcph, *th;

		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
		if (th == NULL)
			break;

143 144
		ad->u.net->sport = th->source;
		ad->u.net->dport = th->dest;
145 146 147 148 149 150 151 152 153
		break;
	}
	case IPPROTO_UDP: {
		struct udphdr _udph, *uh;

		uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
		if (uh == NULL)
			break;

154 155
		ad->u.net->sport = uh->source;
		ad->u.net->dport = uh->dest;
156 157 158 159 160 161 162 163 164
		break;
	}
	case IPPROTO_DCCP: {
		struct dccp_hdr _dccph, *dh;

		dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
		if (dh == NULL)
			break;

165 166
		ad->u.net->sport = dh->dccph_sport;
		ad->u.net->dport = dh->dccph_dport;
167 168 169 170 171 172 173 174
		break;
	}
	case IPPROTO_SCTP: {
		struct sctphdr _sctph, *sh;

		sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
		if (sh == NULL)
			break;
175 176
		ad->u.net->sport = sh->source;
		ad->u.net->dport = sh->dest;
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
		break;
	}
	default:
		ret = -EINVAL;
	}
	return ret;
}
#endif


static inline void print_ipv6_addr(struct audit_buffer *ab,
				   struct in6_addr *addr, __be16 port,
				   char *name1, char *name2)
{
	if (!ipv6_addr_any(addr))
192
		audit_log_format(ab, " %s=%pI6c", name1, addr);
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
	if (port)
		audit_log_format(ab, " %s=%d", name2, ntohs(port));
}

static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
				   __be16 port, char *name1, char *name2)
{
	if (addr)
		audit_log_format(ab, " %s=%pI4", name1, &addr);
	if (port)
		audit_log_format(ab, " %s=%d", name2, ntohs(port));
}

/**
 * dump_common_audit_data - helper to dump common audit data
 * @a : common audit data
 *
 */
static void dump_common_audit_data(struct audit_buffer *ab,
				   struct common_audit_data *a)
{
214
	char comm[sizeof(current->comm)];
215

216 217 218 219 220 221 222
	/*
	 * To keep stack sizes in check force programers to notice if they
	 * start making this union too large!  See struct lsm_network_audit
	 * as an example of how to deal with large data.
	 */
	BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);

223
	audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
224
	audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(comm)));
225 226

	switch (a->type) {
227
	case LSM_AUDIT_DATA_NONE:
228
		return;
229 230 231 232 233 234
	case LSM_AUDIT_DATA_IPC:
		audit_log_format(ab, " key=%d ", a->u.ipc_id);
		break;
	case LSM_AUDIT_DATA_CAP:
		audit_log_format(ab, " capability=%d ", a->u.cap);
		break;
235 236 237
	case LSM_AUDIT_DATA_PATH: {
		struct inode *inode;

238
		audit_log_d_path(ab, " path=", &a->u.path);
239

240
		inode = d_backing_inode(a->u.path.dentry);
241 242 243 244 245
		if (inode) {
			audit_log_format(ab, " dev=");
			audit_log_untrustedstring(ab, inode->i_sb->s_id);
			audit_log_format(ab, " ino=%lu", inode->i_ino);
		}
246 247
		break;
	}
248 249 250 251 252 253 254 255 256 257 258 259 260
	case LSM_AUDIT_DATA_FILE: {
		struct inode *inode;

		audit_log_d_path(ab, " path=", &a->u.file->f_path);

		inode = file_inode(a->u.file);
		if (inode) {
			audit_log_format(ab, " dev=");
			audit_log_untrustedstring(ab, inode->i_sb->s_id);
			audit_log_format(ab, " ino=%lu", inode->i_ino);
		}
		break;
	}
261 262 263 264 265 266 267 268 269 270 271 272
	case LSM_AUDIT_DATA_IOCTL_OP: {
		struct inode *inode;

		audit_log_d_path(ab, " path=", &a->u.op->path);

		inode = a->u.op->path.dentry->d_inode;
		if (inode) {
			audit_log_format(ab, " dev=");
			audit_log_untrustedstring(ab, inode->i_sb->s_id);
			audit_log_format(ab, " ino=%lu", inode->i_ino);
		}

273
		audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
274 275
		break;
	}
276 277 278 279 280 281
	case LSM_AUDIT_DATA_DENTRY: {
		struct inode *inode;

		audit_log_format(ab, " name=");
		audit_log_untrustedstring(ab, a->u.dentry->d_name.name);

282
		inode = d_backing_inode(a->u.dentry);
283 284 285 286 287
		if (inode) {
			audit_log_format(ab, " dev=");
			audit_log_untrustedstring(ab, inode->i_sb->s_id);
			audit_log_format(ab, " ino=%lu", inode->i_ino);
		}
288
		break;
289 290 291 292 293 294 295 296 297 298 299 300 301
	}
	case LSM_AUDIT_DATA_INODE: {
		struct dentry *dentry;
		struct inode *inode;

		inode = a->u.inode;
		dentry = d_find_alias(inode);
		if (dentry) {
			audit_log_format(ab, " name=");
			audit_log_untrustedstring(ab,
					 dentry->d_name.name);
			dput(dentry);
		}
302 303 304
		audit_log_format(ab, " dev=");
		audit_log_untrustedstring(ab, inode->i_sb->s_id);
		audit_log_format(ab, " ino=%lu", inode->i_ino);
305 306
		break;
	}
307 308
	case LSM_AUDIT_DATA_TASK: {
		struct task_struct *tsk = a->u.tsk;
309
		if (tsk) {
310
			pid_t pid = task_tgid_nr(tsk);
311
			if (pid) {
312
				char comm[sizeof(tsk->comm)];
313
				audit_log_format(ab, " opid=%d ocomm=", pid);
314 315
				audit_log_untrustedstring(ab,
				    memcpy(comm, tsk->comm, sizeof(comm)));
316
			}
317 318
		}
		break;
319
	}
320
	case LSM_AUDIT_DATA_NET:
321 322
		if (a->u.net->sk) {
			struct sock *sk = a->u.net->sk;
323 324 325 326 327 328 329 330
			struct unix_sock *u;
			int len = 0;
			char *p = NULL;

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

331 332
				print_ipv4_addr(ab, inet->inet_rcv_saddr,
						inet->inet_sport,
333
						"laddr", "lport");
334 335
				print_ipv4_addr(ab, inet->inet_daddr,
						inet->inet_dport,
336 337 338
						"faddr", "fport");
				break;
			}
339
#if IS_ENABLED(CONFIG_IPV6)
340 341 342
			case AF_INET6: {
				struct inet_sock *inet = inet_sk(sk);

343
				print_ipv6_addr(ab, &sk->sk_v6_rcv_saddr,
344
						inet->inet_sport,
345
						"laddr", "lport");
346
				print_ipv6_addr(ab, &sk->sk_v6_daddr,
347
						inet->inet_dport,
348 349 350
						"faddr", "fport");
				break;
			}
351
#endif
352 353
			case AF_UNIX:
				u = unix_sk(sk);
354 355
				if (u->path.dentry) {
					audit_log_d_path(ab, " path=", &u->path);
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
					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;
			}
		}

371
		switch (a->u.net->family) {
372
		case AF_INET:
373 374
			print_ipv4_addr(ab, a->u.net->v4info.saddr,
					a->u.net->sport,
375
					"saddr", "src");
376 377
			print_ipv4_addr(ab, a->u.net->v4info.daddr,
					a->u.net->dport,
378 379 380
					"daddr", "dest");
			break;
		case AF_INET6:
381 382
			print_ipv6_addr(ab, &a->u.net->v6info.saddr,
					a->u.net->sport,
383
					"saddr", "src");
384 385
			print_ipv6_addr(ab, &a->u.net->v6info.daddr,
					a->u.net->dport,
386 387 388
					"daddr", "dest");
			break;
		}
389
		if (a->u.net->netif > 0) {
390 391 392
			struct net_device *dev;

			/* NOTE: we always use init's namespace */
393
			dev = dev_get_by_index(&init_net, a->u.net->netif);
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
			if (dev) {
				audit_log_format(ab, " netif=%s", dev->name);
				dev_put(dev);
			}
		}
		break;
#ifdef CONFIG_KEYS
	case LSM_AUDIT_DATA_KEY:
		audit_log_format(ab, " key_serial=%u", a->u.key_struct.key);
		if (a->u.key_struct.key_desc) {
			audit_log_format(ab, " key_desc=");
			audit_log_untrustedstring(ab, a->u.key_struct.key_desc);
		}
		break;
#endif
409 410 411 412
	case LSM_AUDIT_DATA_KMOD:
		audit_log_format(ab, " kmod=");
		audit_log_untrustedstring(ab, a->u.kmod_name);
		break;
413 414 415 416 417 418 419 420 421 422 423
	case LSM_AUDIT_DATA_IBPKEY: {
		struct in6_addr sbn_pfx;

		memset(&sbn_pfx.s6_addr, 0,
		       sizeof(sbn_pfx.s6_addr));
		memcpy(&sbn_pfx.s6_addr, &a->u.ibpkey->subnet_prefix,
		       sizeof(a->u.ibpkey->subnet_prefix));
		audit_log_format(ab, " pkey=0x%x subnet_prefix=%pI6c",
				 a->u.ibpkey->pkey, &sbn_pfx);
		break;
	}
424 425 426 427 428
	case LSM_AUDIT_DATA_IBENDPORT:
		audit_log_format(ab, " device=%s port_num=%u",
				 a->u.ibendport->dev_name,
				 a->u.ibendport->port);
		break;
429 430 431 432 433 434
	} /* switch (a->type) */
}

/**
 * common_lsm_audit - generic LSM auditing function
 * @a:  auxiliary audit data
435 436
 * @pre_audit: lsm-specific pre-audit callback
 * @post_audit: lsm-specific post-audit callback
437 438 439 440
 *
 * setup the audit buffer for common security information
 * uses callback to print LSM specific information
 */
441 442 443
void common_lsm_audit(struct common_audit_data *a,
	void (*pre_audit)(struct audit_buffer *, void *),
	void (*post_audit)(struct audit_buffer *, void *))
444 445 446 447 448 449
{
	struct audit_buffer *ab;

	if (a == NULL)
		return;
	/* we use GFP_ATOMIC so we won't sleep */
450
	ab = audit_log_start(audit_context(), GFP_ATOMIC | __GFP_NOWARN,
451
			     AUDIT_AVC);
452 453 454 455

	if (ab == NULL)
		return;

456 457
	if (pre_audit)
		pre_audit(ab, a);
458 459 460

	dump_common_audit_data(ab, a);

461 462
	if (post_audit)
		post_audit(ab, a);
463 464 465

	audit_log_end(ab);
}